/* ==========================================================================
   SACHDEVA GROUP — ABOUT, premium layer
   ==========================================================================
   Scope : about_us.html ONLY. Loaded last, after css/icons.css.

   WHY A PAGE-SPECIFIC FILE
     The About page carries the whole company story, so it is the one worth
     spending depth on. Its `.abt-*` rules live in css/index-theme.css and are
     shared with nothing, but they cannot be re-themed there without touching
     the rest of the site, and they cannot be scoped by section id inside a
     shared file either: #profile also exists on sspsb.html and jjsb.html.

   THE LANGUAGE — light, rounded, generous
     Built to a supplied reference for the Group Profile block. Its rules,
     applied to every section on the page so it reads as one design rather
     than one styled block and six others:

       GROUND   near-white with a pale blue wash, not flat #fff. Dark sections
                keep their place in the rhythm but take the same soft, rounded
                treatment in a dark key.
       RADIUS   16px on cards and media, 12px on panels, full pills on
                eyebrows, captions and buttons. Nothing is square.
       SHADOW   wide, soft and low-contrast — light falling on paper, not a
                hard drop shadow. Two steps only: rest and lift.
       TWO-TONE the display heading runs dark navy, with the emphasised words
                in a gold gradient. That is the page's one moment of warmth;
                everything else is cyan.
       NUMERALS thin and large. Years, tonnages and counts are the evidence on
                this page, so they are set like evidence, not like labels.

     This replaces an earlier squared, dark, industrial treatment of the same
     sections. The two do not mix, so none of it survives.

   MOTION
     Driven by js/page-fx.js + js/marine.js + js/index-motion.js. GSAP is
     deliberately absent: js/motion.js is index-only and would set
     SG_MOTION_ENGINE='gsap', standing marine.js and index-motion.js down —
     and this page needs both. Every transition here is CSS, fired by classes
     those engines already set. Where a state has to appear on scroll it hangs
     off `.sg-shown`, not `.mrn-in`; see section 11 for why.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

#profile,
#heritage,
#vision,
#compliance,
#units,
#testimonials,
#creds {
    --ab-ink: #0b1f33;
    --ab-body: #55708a;
    --ab-card: #ffffff;
    --ab-card-dark: linear-gradient(165deg, #12365c 0%, #0a2440 55%, #071a2e 100%);
    --ab-ring: 1px solid rgba(11, 31, 51, .07);
    --ab-ring-dark: 1px solid rgba(53, 198, 244, .16);

    --ab-r: 16px;
    --ab-r-panel: 12px;

    --ab-soft: 0 18px 40px -22px rgba(16, 42, 67, .22);
    --ab-lift: 0 34px 66px -28px rgba(16, 42, 67, .32);
    --ab-lift-dark: 0 34px 66px -28px rgba(4, 18, 31, .8);

    --ab-gold: linear-gradient(92deg, #e8a217 0%, #ffc94d 55%, #ffb524 100%);
    --ab-ease: cubic-bezier(.16, 1, .3, 1);
}

/* ==========================================================================
   2. FILL — the page was not using the screen
   ==========================================================================
   marine.css caps .mrn-container at 1240px. On a 1440 display that leaves
   200px unused; on a 1920 display it leaves 680px, and the page reads as a
   column floating in the middle of the window rather than as a layout. Every
   section measured 96% of a 1240 container — the content was not thin, the
   container was.

   Widened to 1440 on this page only, and the vertical padding comes down from
   118px to a fluid 82-104px. Measured before: each section carried 236px of
   padding around 470-1148px of content, so the shorter blocks were half air.
   ========================================================================== */

#profile > .mrn-container,
#heritage > .mrn-container,
#vision > .mrn-container,
#compliance > .mrn-container,
#units > .mrn-container,
#testimonials > .mrn-container,
#creds > .mrn-container {
    max-width: 1440px;
    padding-left: clamp(24px, 3.4vw, 48px);
    padding-right: clamp(24px, 3.4vw, 48px);
}

#profile,
#heritage,
#vision,
#compliance,
#units,
#testimonials,
#creds {
    padding: clamp(82px, 6.4vw, 104px) 0;
}

/* ==========================================================================
   3. GROUNDS — near-white with a wash, never flat
   ========================================================================== */

#profile,
#compliance,
#testimonials {
    background:
        radial-gradient(900px 520px at 12% 0%, rgba(34, 179, 230, .07), transparent 62%),
        radial-gradient(760px 480px at 92% 88%, rgba(255, 201, 77, .06), transparent 66%),
        linear-gradient(180deg, #ffffff 0%, #f6fafd 100%);
}

#vision,
#creds {
    background:
        radial-gradient(820px 480px at 88% 6%, rgba(34, 179, 230, .10), transparent 64%),
        linear-gradient(180deg, #f4f9fd 0%, #eef5fb 100%);
}

/* ==========================================================================
   4. SHARED TYPE — eyebrow pill, two-tone heading, prose
   ========================================================================== */

#profile .mrn-eyebrow,
#heritage .mrn-eyebrow,
#vision .mrn-eyebrow,
#compliance .mrn-eyebrow,
#units .mrn-eyebrow,
#testimonials .mrn-eyebrow,
#creds .mrn-eyebrow {
    padding: 9px 20px 9px 16px;
    border: 1px solid rgba(11, 31, 51, .10);
    border-radius: 999px;
    background: rgba(255, 255, 255, .8);
    box-shadow: var(--ab-soft);
    font-size: 11.5px;
    letter-spacing: 3px;
    color: #12496b;
}

/* the one warm accent in the eyebrow */
#profile .mrn-eyebrow::before,
#heritage .mrn-eyebrow::before,
#vision .mrn-eyebrow::before,
#compliance .mrn-eyebrow::before,
#units .mrn-eyebrow::before,
#testimonials .mrn-eyebrow::before,
#creds .mrn-eyebrow::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #f0a500;
    flex: none;
}

#heritage .mrn-eyebrow,
#units .mrn-eyebrow {
    border-color: rgba(53, 198, 244, .24);
    background: rgba(10, 36, 64, .55);
    box-shadow: none;
    color: #9fdcf7;
}

/* --- the two-tone display heading ---------------------------------------- */
#profile .mrn-title,
#compliance .mrn-title,
#testimonials .mrn-title,
#vision .mrn-title {
    color: var(--ab-ink);
    letter-spacing: -.4px;
}

#profile .mrn-title em,
#heritage .mrn-title em,
#vision .mrn-title em,
#compliance .mrn-title em,
#units .mrn-title em,
#testimonials .mrn-title em,
#creds .mrn-title em {
    font-style: normal;
    background: var(--ab-gold);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

#profile .mrnp-prose > p,
#compliance .mrn-lead,
#testimonials .mrn-lead {
    color: var(--ab-body);
    font-size: 16.5px;
    line-height: 1.78;
}

/* --- the lead paragraph: drop cap against a cyan rule -------------------- */
#profile .mrnp-prose--lead > p:first-of-type {
    position: relative;
    padding-left: 26px;
    border-left: 3px solid var(--cyan);
    font-size: 18.5px;
    line-height: 1.7;
    color: #2c4b66;
}

#profile .mrnp-prose--lead > p:first-of-type::first-letter {
    float: left;
    margin: 4px 14px 0 0;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--font-display);
    font-weight: 300;
    font-size: 62px;
    line-height: .82;
    color: var(--cyan-deep);
    -webkit-text-fill-color: currentColor;
}

/* ==========================================================================
   5. #banner — the night-yard photograph
   ==========================================================================
   The banner is .mrnp-hero, shared with every inner page, and css/page-fx.css
   grades its photograph for the stock daylight yard shots the other pages
   carry: saturate(.42) brightness(.62). That grade is a rescue — it duotones
   a warm image down into the cyan chrome so the two stop arguing.

   images/about/about-banner-night-yard.webp does not need rescuing. It is
   already the palette: a teal night sky over amber sodium lamps, the same two
   hues this page runs everywhere else. Put the shared grade on it and the
   lamps go grey, the sky goes slate, and the one thing worth looking at —
   light on a working quay — flattens into haze. So About opts out and grades
   for itself. None of this is a nudge of the shared rule; it is a different
   intent, which is why it re-states rather than adjusts.

   Only About moves. vision_mission.html and sspsb.html now carry this same
   photograph, and testimonials.html a yard frame of its own, but all of them
   run through the shared page-fx grade — which is the point: the shared rule
   is built to rescue an arbitrary yard photograph, and this one does not need
   rescuing.

   WHAT IS DELIBERATELY LEFT ALONE
     transform          js/page-fx.js heroScrub() writes it inline every frame
                        for the scroll parallax and would beat anything stated
                        here anyway, and the 8% overscan it draws its travel
                        budget from (marine-pages.css:26) has to stay exactly
                        as it is.
     .mrnp-hero__grid   the survey grid already sits over the darkest part of
                        the frame, which is where it was working before.

   Width breakpoints for this section live in section 14 with the rest.
   ========================================================================== */

/* --- the photograph ---------------------------------------------------- */

.abt-hero .mrnp-hero__bg {
    /* Colour kept, exposure pulled. .72 is where the sky holds its teal and
       the lamps still burn, without the frame getting bright enough to fight
       white type — the scrim below takes the copy column much further down
       than this on its own. */
    filter: saturate(1.06) contrast(1.08) brightness(.72);

    /* The frame is 3:2; the banner strip is nearer 2.3:1, so `cover` throws
       away a third of the height. Centred, it spends that budget cutting off
       the crane tops — the silhouette the picture is built on — and keeps the
       stacked-plate foreground, which at this size is a dark smudge. Biasing
       the crop upward trades the smudge for the cranes. */
    background-position: 50% 24%;
}

/* --- the light shafts, turned down ------------------------------------- */

/* page-fx.css:168 lays three diagonal shafts over the banner. On the other
   inner pages they are the only light in the frame and they earn their keep.
   Here the photograph brought its own — twenty-odd sodium lamps — and a
   straight pale diagonal drawn across them stops reading as light and starts
   reading as a smear on the lens. Turned down far enough to keep the depth
   and lose the streak; removing the layer outright flattens the sky. */
.abt-hero::after {
    opacity: .34;
}

/* --- the scrim: asymmetric, because the picture is ---------------------- */

/* The copy sits left inside a 640px measure (page-fx.css:238). The lit quay
   runs from the middle of the frame to the right edge. An even wash therefore
   spends its darkness in the wrong place: enough of it to seat the text
   flattens the lamps, and enough to keep the lamps leaves the sub-heading
   sitting on a floodlit superstructure.

   So the scrim is graded along the same axis the photograph is — near-opaque
   under the words, barely there over the lights. The vertical pass keeps its
   original job: dark under the sticky header, dark again at the foot so the
   frame has reached the ink before .pfx-wave hands over to white. The third
   stop is an edge vignette, which is what stops a wide dark photograph from
   drifting off at the corners. */
.abt-hero .mrnp-hero__scrim {
    background:
        linear-gradient(96deg,
            rgba(4, 18, 31, .94) 0%,
            rgba(5, 22, 37, .80) 27%,
            rgba(5, 22, 37, .38) 55%,
            rgba(5, 22, 37, .10) 79%,
            rgba(5, 22, 37, .02) 100%),
        linear-gradient(180deg,
            rgba(4, 18, 31, .72) 0%,
            rgba(4, 18, 31, .12) 33%,
            rgba(4, 18, 31, .30) 66%,
            rgba(4, 18, 31, .94) 100%),
        radial-gradient(118% 104% at 46% 44%,
            transparent 40%,
            rgba(2, 11, 20, .42) 100%);
}

/* --- the lamps, carried past the crop ---------------------------------- */

/* One warm layer, screened, sitting where the sodium lamps already are, so
   the amber in the photograph bleeds into the chrome instead of stopping dead
   at the frame edge. .mrnp-hero sets `isolation: isolate` (page-fx.css:121),
   so the blend cannot reach past the banner into the header above it.
   z-index 2 is over the scrim (1) and under .mrnp-hero__inner (4). */
.abt-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    mix-blend-mode: screen;
    background:
        radial-gradient(44% 32% at 66% 55%, rgba(255, 166, 46, .22), transparent 70%),
        radial-gradient(16% 13% at 85% 53%, rgba(255, 200, 110, .18), transparent 72%),
        radial-gradient(30% 26% at 12% 58%, rgba(255, 176, 70, .08), transparent 72%);
}

/* --- the drifting orbs ------------------------------------------------- */

/* page-fx.css recolours these for a frame with no light of its own — cyan
   top-left, amber parked off the bottom-right corner. Here the amber one is
   the only thing on the layer that can move, so it is worth moving: sat over
   the lamp cluster it reads as the glow breathing, rather than as a blob in
   a corner. marine.css:1687 mrnOrb carries it +70/+50 and up to scale 1.22,
   which is the room left on the right. */
.abt-hero .mrnp-hero__orb--b {
    width: 380px;
    height: 300px;
    right: 12%;
    bottom: 26%;
    background: radial-gradient(circle, rgba(255, 171, 46, .26), transparent 68%);
}

/* The sky is already this colour. At page-fx.css's .40 the cyan orb doubled
   it into a bruise behind the breadcrumb. */
.abt-hero .mrnp-hero__orb--a {
    background: radial-gradient(circle, rgba(34, 179, 230, .26), transparent 66%);
}

/* ==========================================================================
   6. #profile — photograph, story, evidence strip
   ========================================================================== */

#profile .abt-split {
    gap: 70px;
    align-items: center;
}

#profile .abt-frame {
    border-radius: var(--ab-r);
    border: 1px solid rgba(255, 255, 255, .9);
    box-shadow: var(--ab-lift);
    transition: transform .6s var(--ab-ease), box-shadow .6s var(--ab-ease);
}

#profile .abt-frame img {
    filter: saturate(.92) contrast(1.03);
    transition: filter .8s var(--ab-ease), transform 1.2s var(--ab-ease);
}

#profile .abt-split__media:hover .abt-frame img {
    filter: none;
    transform: scale(1.035);
}

/* the duotone wash the dark theme applied is far too heavy for this ground */
#profile .abt-frame::after {
    background: linear-gradient(160deg, rgba(10, 35, 64, .10) 0%, transparent 45%, rgba(34, 179, 230, .10) 100%);
}

/* --- the caption pill, overlapping the photograph's lower-left ----------- */
#profile .abt-split__media {
    position: relative;
    padding-bottom: 20px;
}

#profile .abt-frame__cap {
    position: absolute;
    left: 18px;
    bottom: 0;
    z-index: 3;
    margin: 0;
    padding: 11px 20px 11px 16px;
    border-radius: 999px;
    background: linear-gradient(120deg, #0d2340 0%, #08192d 100%);
    box-shadow: var(--ab-soft);
    color: #ffffff;
    font-size: 11px;
    letter-spacing: 2.4px;
}

#profile .abt-frame__cap::before {
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: var(--cyan-bright);
}

/* --- the CTA, a full pill ------------------------------------------------ */
#profile .abt-split__body .mrn-btn {
    border-radius: 999px;
    padding: 19px 34px;
    background: linear-gradient(100deg, #0d2f52 0%, #0f4a6e 55%, #12607f 100%);
    border: 0;
    color: #fff;
    box-shadow: var(--ab-lift);
    transition: transform .2s var(--ab-ease), box-shadow .2s var(--ab-ease);
}

#profile .abt-split__body .mrn-btn:hover {
    transform: translateY(-3px);
    box-shadow: 0 40px 70px -26px rgba(16, 42, 67, .45);
}

/* ==========================================================================
   7. THE EVIDENCE STRIP — 1983 / 4,950 / 100,000+ / 37 + 36
   ==========================================================================
   marine-pages.css paints this as a solid navy band. On this ground it should
   read as a light panel of figures, with the numerals doing the work.
   ========================================================================== */

#profile .mrnp-strip {
    margin-top: 76px;
    padding: 30px 16px;
    border-radius: var(--ab-r-panel);
    border: var(--ab-ring);
    background:
        radial-gradient(700px 300px at 8% 0%, rgba(34, 179, 230, .10), transparent 70%),
        radial-gradient(600px 280px at 96% 100%, rgba(255, 201, 77, .09), transparent 72%),
        linear-gradient(180deg, #ffffff 0%, #f5fafd 100%);
    box-shadow: var(--ab-soft);

    /* the 3D room the four cells stand in */
    perspective: 1100px;
    perspective-origin: 50% 40%;
}

#profile .mrnp-strip::before {
    display: none;
}

/* --- 6.1 the cells ------------------------------------------------------ */

#profile .mrnp-strip > div {
    position: relative;
    padding: 24px 16px;
    border-right: 1px solid rgba(11, 31, 51, .09);
    border-radius: 14px;
    transform-style: preserve-3d;
    transition: transform .55s var(--ab-ease);
}

#profile .mrnp-strip > div:last-child {
    border-right: 0;
}

/* the plate that rises behind the figures on hover. It sits BEHIND them in Z
   rather than above them in z-index, so the numerals genuinely stand off it. */
#profile .mrnp-strip > div::after {
    content: "";
    position: absolute;
    inset: 0;
    /* the cell is a stacking context (preserve-3d), so this stays inside it
       and simply sits under the figures. Without it the plate depends on the
       3D surviving to stay behind — and anything that flattens the cell puts
       an opaque panel straight over the numerals. */
    z-index: -1;
    border-radius: 14px;
    background: linear-gradient(180deg, #ffffff 0%, #edf7fd 100%);
    border: 1px solid rgba(34, 179, 230, .28);
    box-shadow: 0 30px 48px -22px rgba(16, 42, 67, .42);
    opacity: 0;
    transform: translateZ(-28px) scale(.96);
    transition: opacity .5s var(--ab-ease), transform .55s var(--ab-ease);
}

/* --- 6.2 the figures ---------------------------------------------------- */

#profile .mrnp-strip strong {
    display: block;
    font-weight: 500;
    font-size: clamp(38px, 3.1vw, 50px);
    line-height: 1;
    letter-spacing: .5px;
    /* --cyan-deep (#1195cf) measures 3.4:1 against this near-white panel. That
       clears AA for large text on a technicality and still reads washed out,
       which is the complaint. This is 5.6:1 and stays in the cyan family. */
    color: #0b6d97;
    transform: translateZ(0);
    transition: transform .55s var(--ab-ease), color .45s var(--ab-ease);
}

/* THE FIGURE THAT COUNTS IS A SPAN, and it must not be read as a label.
   `1983` is written `<strong><span data-count="1983">0</span></strong>` so the
   counter has something to animate. A `.mrnp-strip span` rule therefore lands
   on it as well as on the caption underneath, and 1983 was rendering at 11px
   in grey — as a block, on its own line — while 4,950 and 100,000+ sat at
   50px in cyan beside it. It inherits the numeral now. */
#profile .mrnp-strip strong span {
    display: inline;
    margin: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: none;
}

#profile .mrnp-strip strong i,
#profile .mrnp-strip strong em {
    font-style: normal;
    font-size: .5em;
    vertical-align: super;
    color: #d99000;
}

/* the caption — a DIRECT child of the cell, which is the whole point */
#profile .mrnp-strip > div > span {
    display: block;
    margin-top: 12px;
    color: #4d6a86;
    font-size: 11px;
    letter-spacing: 2.4px;
    transform: translateZ(0);
    transition: transform .55s var(--ab-ease), color .45s var(--ab-ease);
}

/* --- 6.3 the 3D hover --------------------------------------------------- */

@media (hover: hover) and (prefers-reduced-motion: no-preference) {

    #profile .mrnp-strip > div:hover {
        transform: translateY(-10px) rotateX(9deg) scale(1.03);
    }

    #profile .mrnp-strip > div:hover::after {
        opacity: 1;
        transform: translateZ(-28px) scale(1);
    }

    #profile .mrnp-strip > div:hover strong {
        transform: translateZ(46px);
    }

    #profile .mrnp-strip > div:hover > span {
        transform: translateZ(24px);
        color: var(--ab-ink);
    }

    /* the divider would otherwise cut straight through the raised plate — on
       the hovered cell and on the one to its left */
    #profile .mrnp-strip > div:hover,
    #profile .mrnp-strip > div:has(+ div:hover) {
        border-right-color: transparent;
    }
}

/* MOTION OFF, AFFORDANCE ON.
   A hover built only out of transforms disappears completely for anyone who
   has asked for reduced motion — they get four figures that look clickable
   and answer to nothing. The plate and the ink still respond here; the cell
   simply does not travel. */
@media (hover: hover) and (prefers-reduced-motion: reduce) {

    /* opacity ONLY. `transform: none` here would drop the plate's
       translateZ(-28px), landing it in the same plane as the figures — and
       because ::after paints after its content, it covered them completely. */
    #profile .mrnp-strip > div:hover::after {
        opacity: 1;
    }

    #profile .mrnp-strip > div:hover strong {
        color: #08587a;
    }

    #profile .mrnp-strip > div:hover > span {
        color: var(--ab-ink);
    }

    #profile .mrnp-strip > div:hover,
    #profile .mrnp-strip > div:has(+ div:hover) {
        border-right-color: transparent;
    }
}

/* ==========================================================================
   8. #heritage — the four dates, in the same rounded key
   ========================================================================== */

#heritage .abt-time {
    gap: 24px;
}

#heritage .abt-time__item {
    border-radius: var(--ab-r);
    background: var(--ab-card-dark);
    border: var(--ab-ring-dark);
    padding: 36px 26px 30px;
    box-shadow: var(--ab-lift-dark);
    transition: transform .55s var(--ab-ease), box-shadow .55s var(--ab-ease), border-color .55s var(--ab-ease);
}

/* the rule across the plate's head, drawn as its own card arrives */
#heritage .abt-time__item::before {
    left: 26px;
    right: 26px;
    height: 3px;
    border-radius: 3px;
    background: linear-gradient(90deg, var(--cyan-bright), rgba(34, 179, 230, .1));
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .8s var(--ab-ease);
}

#heritage .abt-time__item.sg-shown::before,
#heritage .abt-time__item:hover::before {
    transform: scaleX(1);
}

#heritage .abt-time__item:hover {
    transform: translateY(-8px);
    border-color: rgba(53, 198, 244, .42);
    box-shadow: 0 40px 74px -28px rgba(34, 179, 230, .5);
}

#heritage .abt-time__year {
    font-weight: 200;
    font-size: 34px;
    letter-spacing: 0;
    color: var(--cyan-bright);
}

/* ==========================================================================
   9. #vision — a tideline band, and two plates floating over it
   ==========================================================================
   WHAT WAS WRONG
     Two identical white rectangles side by side, each with a chip icon, a
     19px heading and a 64-word paragraph set as one undifferentiated grey
     block. Nothing separated VISION from MISSION but the icon, and the
     photograph above ran 1329px wide from an 800x500 source — a 66% upscale,
     which is where the softness came from.

   THE 3D WAS NEVER RENDERING
     .mrnp-icard declares `transform-style: preserve-3d` AND `overflow:
     hidden` (marine-pages.css:300, restated page-fx.css:473). overflow is a
     grouping property: it forces the used transform-style to flat. So
     `.mrnp-icard:hover > * { transform: translateZ(34px) }` at
     marine-pages.css:349 has never moved anything, on any page. No ancestor
     set `perspective` either, so it was dead twice over.

     Measured in an isolated rig — a child at translateZ(38px) under
     perspective:1100px renders 74.50px wide, and 71.92px once flattened:
       FLATTENS   overflow:hidden|clip · isolation:isolate · opacity:.99
                  filter:* · will-change:opacity
       SAFE       contain:paint · will-change:transform · border-radius
                  box-shadow
     That is why this block uses its own `.viz-*` classes rather than
     .mrnp-icard: inheriting that card meant inheriting the one declaration
     that cancels the effect being asked for. It is also why .edge-sweep must
     never be put on a .d3-card — `isolation: isolate` flattens it the same
     way.

   THE COMPOSITION
     The band is capped at 1100px so the photograph is never blown past its
     source, and carries a scrim so it reads as depth rather than as a soft
     picture. The two plates are pulled up over its lower edge, which puts
     them physically in front of the tideline instead of stacked under it.
     They are deliberately NOT symmetrical: vision is a light plate looking
     out, mission is a dark plate — the yard at work. Each statement leads
     with its own first sentence set large, with the remainder beneath it as
     supporting text, so neither is a wall of grey.
   ========================================================================== */

#vision .viz {
    position: relative;
    margin-top: 52px;
}

/* --- 8.1 the band ------------------------------------------------------- */

#vision .viz__band {
    position: relative;
    /* the source is 800x500; past ~1100 it is being invented */
    max-width: 1100px;
    margin: 0 auto;
    border-radius: var(--ab-r);
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, .9);
    box-shadow: var(--ab-lift);
}

/* SAFE: the band is a sibling of the stage, never an ancestor of a plate, so
   its overflow:hidden cannot flatten the 3D above. */

#vision .viz__band img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 21 / 9;
    object-fit: cover;
    object-position: 50% 54%;
    filter: saturate(.88) contrast(1.04);
}

@supports not (aspect-ratio: 1) {
    #vision .viz__band img {
        height: 420px;
    }
}

/* the plates sit on the lower half, so the scrim is weighted there */
#vision .viz__band::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(6, 24, 42, .06) 0%, rgba(6, 24, 42, .16) 38%, rgba(6, 24, 42, .74) 100%);
}

#vision .viz__waterline {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 32%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(53, 198, 244, .75) 22%, rgba(53, 198, 244, .75) 78%, transparent);
    opacity: .65;
}

/* --- 8.2 the stage ------------------------------------------------------ */

#vision .viz__stage {
    position: relative;
    z-index: 2;
    max-width: 1280px;
    /* pull the plates up over the band's lower edge */
    margin: -136px auto 0;
    padding: 0 clamp(0px, 1.4vw, 20px);
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
    gap: 30px;

}

/* --- 8.3 the plates ----------------------------------------------------- */

#vision .viz-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 40px 38px 38px;
    border-radius: var(--ab-r);
    will-change: transform;
    transition: box-shadow .55s var(--ab-ease), border-color .55s var(--ab-ease);

    /* THE 3D ROOM IS THE PLATE, NOT THE STAGE.
       One stage-wide perspective projects from a single vanishing point, so
       content on the left plate splays LEFT as it rises and overruns the
       plate's own edge — measured, the heading crossed it. A perspective per
       plate, origin at its own centre, lifts each element straight towards
       the viewer instead.
       Nothing here may set overflow, isolation, opacity or filter: each of
       those is a grouping property and would flatten the depth outright. */
    perspective: 900px;
    perspective-origin: 50% 46%;
    transform-style: preserve-3d;
}

/* the plate's own movement belongs to data-mrnp-tilt, which writes an inline
   transform — a CSS hover transform here would fight it every frame */

#vision .viz-card--vision {
    background: linear-gradient(178deg, #ffffff 0%, #f1f8fd 100%);
    border: var(--ab-ring);
    box-shadow: var(--ab-soft);
}

#vision .viz-card--mission {
    background: var(--ab-card-dark);
    border: var(--ab-ring-dark);
    box-shadow: var(--ab-lift-dark);
}

/* --- 8.4 plate contents ------------------------------------------------- */

#vision .viz-card__no {
    position: absolute;
    top: 26px;
    right: 30px;
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 200;
    font-size: 54px;
    line-height: 1;
    letter-spacing: 1px;
    transform: translateZ(8px);
}

#vision .viz-card--vision .viz-card__no {
    color: rgba(11, 31, 51, .13);
}

#vision .viz-card--mission .viz-card__no {
    color: rgba(159, 220, 247, .20);
}

#vision .viz-card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    margin-bottom: 24px;
    border-radius: 16px;
    transform: translateZ(30px);
    transition: transform .55s var(--ab-ease), background .55s var(--ab-ease),
        color .55s var(--ab-ease), box-shadow .55s var(--ab-ease);
}

#vision .viz-card__icon svg {
    width: 28px;
    height: 28px;
}

#vision .viz-card--vision .viz-card__icon {
    background: linear-gradient(140deg, rgba(34, 179, 230, .16), rgba(34, 179, 230, .06));
    border: 1px solid rgba(34, 179, 230, .22);
    color: #0b6d97;
}

#vision .viz-card--mission .viz-card__icon {
    background: linear-gradient(140deg, rgba(53, 198, 244, .18), rgba(53, 198, 244, .05));
    border: 1px solid rgba(53, 198, 244, .28);
    color: #6fd3f7;
}

#vision .viz-card h3 {
    margin: 0;
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 500;
    font-size: 27px;
    line-height: 1.1;
    letter-spacing: .3px;
    text-transform: uppercase;
    transform: translateZ(24px);
}

#vision .viz-card--vision h3 {
    color: var(--ab-ink);
}

#vision .viz-card--mission h3 {
    background: var(--ab-gold);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* a cut edge under the heading rather than a border — the yard's own line */
#vision .viz-card__seam {
    display: block;
    width: 66px;
    height: 3px;
    margin: 18px 0 22px;
    border-radius: 2px;
    transform: translateZ(18px);
}

#vision .viz-card--vision .viz-card__seam {
    background: linear-gradient(90deg, #1195cf, rgba(17, 149, 207, .12));
}

#vision .viz-card--mission .viz-card__seam {
    background: repeating-linear-gradient(135deg, #f0a500 0 7px, rgba(240, 165, 0, .18) 7px 14px);
}

/* the lead sentence carries the statement; the rest supports it */
#vision .viz-card__lead {
    margin: 0 0 16px;
    font-size: 17.5px;
    line-height: 1.62;
    font-weight: 500;
    transform: translateZ(13px);
}

#vision .viz-card--vision .viz-card__lead {
    color: var(--ab-ink);
}

#vision .viz-card--mission .viz-card__lead {
    color: #eaf6fd;
}

#vision .viz-card__body {
    margin: 0;
    font-size: 15px;
    line-height: 1.78;
    transform: translateZ(6px);
}

#vision .viz-card--vision .viz-card__body {
    color: var(--ab-body);
}

#vision .viz-card--mission .viz-card__body {
    color: rgba(190, 214, 232, .88);
}

/* --- 8.5 the 3D hover --------------------------------------------------- */

#vision .viz-card--vision:hover {
    border-color: rgba(34, 179, 230, .42);
    box-shadow: var(--ab-lift);
}

#vision .viz-card--mission:hover {
    border-color: rgba(53, 198, 244, .5);
    box-shadow: 0 44px 80px -30px rgba(34, 179, 230, .45);
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {

    #vision .viz-card h3,
    #vision .viz-card__seam,
    #vision .viz-card__lead,
    #vision .viz-card__body,
    #vision .viz-card__no {
        transition: transform .55s var(--ab-ease), width .55s var(--ab-ease);
    }

    /* the plate stays put — the tilt owns that — and its contents come
       forward off the face, which is what reads as depth */
    /* the icon sits in the top-left corner, which is the furthest point from
       the plate's perspective origin, so it travels outward fastest as it
       rises. Measured at translateZ(74) with rotate(-6deg) scale(1.05) it
       cleared the plate's own edge by 5.4px. This is the limit that stays in. */
    #vision .viz-card:hover .viz-card__icon {
        transform: translateZ(52px) rotate(-4deg);
    }

    #vision .viz-card:hover h3 {
        transform: translateZ(54px);
    }

    #vision .viz-card:hover .viz-card__seam {
        transform: translateZ(42px);
        width: 108px;
    }

    #vision .viz-card:hover .viz-card__lead {
        transform: translateZ(30px);
    }

    #vision .viz-card:hover .viz-card__body {
        transform: translateZ(14px);
    }

    #vision .viz-card:hover .viz-card__no {
        transform: translateZ(20px);
    }

    #vision .viz-card--vision:hover .viz-card__icon {
        background: linear-gradient(140deg, #1195cf, #35c6f4);
        color: #fff;
        box-shadow: 0 18px 30px -14px rgba(17, 149, 207, .7);
    }

    #vision .viz-card--mission:hover .viz-card__icon {
        background: var(--ab-gold);
        color: #07182e;
        box-shadow: 0 18px 30px -14px rgba(240, 165, 0, .55);
    }
}

/* MOTION OFF, AFFORDANCE ON — the plate still answers, it just does not move */
@media (hover: hover) and (prefers-reduced-motion: reduce) {

    #vision .viz-card--vision:hover .viz-card__icon {
        background: linear-gradient(140deg, #1195cf, #35c6f4);
        color: #fff;
    }

    #vision .viz-card--mission:hover .viz-card__icon {
        background: var(--ab-gold);
        color: #07182e;
    }

    #vision .viz-card:hover .viz-card__seam {
        width: 108px;
    }
}

/* ==========================================================================
   10. #compliance — five standards, set as compliance plates
   ==========================================================================
   Before: five identical white boxes, each an acronym over its full name.
   Nothing told you IMO was a UN agency and Basel a treaty, the acronyms sat
   at font-weight 200 in --cyan-deep (#1195cf, 3.4:1 on this ground — the same
   washed-out value the stat strip had), and the plate carried `overflow:
   hidden`, which flattens transform-style outright. So the tilt on each item
   had no depth to reveal.

   Now each plate carries a seal, an index, and what kind of instrument it is
   — the one piece of information that makes the five distinguishable rather
   than interchangeable. Depth is real: perspective on the plate itself, and
   the contents rise off its face on hover.
   ========================================================================== */

#compliance .abt-comply {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 18px;
    margin-top: 54px;
    padding: 0;
    list-style: none;
}

#compliance .cmp {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 22px 20px 24px;
    border-radius: var(--ab-r-panel);
    background: linear-gradient(178deg, #ffffff 0%, #f4fafd 100%);
    border: var(--ab-ring);
    box-shadow: var(--ab-soft);
    transition: box-shadow .5s var(--ab-ease), border-color .5s var(--ab-ease),
        background .5s var(--ab-ease);

    /* the 3D room is the plate. NOTE the absence of `overflow: hidden` — it
       is a grouping property and would flatten every translateZ below. The
       top rule is inset instead of clipped, which is why none is needed. */
    perspective: 800px;
    perspective-origin: 50% 40%;
    transform-style: preserve-3d;
}

/* the rule that draws in on approach — inset and self-rounded so the plate
   never needs to clip it */
#compliance .cmp__rule {
    position: absolute;
    top: 0;
    left: 14px;
    right: 14px;
    height: 3px;
    border-radius: 0 0 3px 3px;
    background: linear-gradient(90deg, var(--cyan-bright, #35c6f4), rgba(34, 179, 230, .12));
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .6s var(--ab-ease), background .5s var(--ab-ease);
}

#compliance .cmp.sg-shown .cmp__rule,
#compliance .cmp:hover .cmp__rule {
    transform: scaleX(1);
}

/* --- 9.1 the head row: seal + index ------------------------------------- */

#compliance .cmp__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin-bottom: 18px;
    transform: translateZ(16px);
}

#compliance .cmp__seal {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: rgba(34, 179, 230, .12);
    border: 1px solid rgba(34, 179, 230, .3);
    color: #0b6d97;
    transition: transform .5s var(--ab-ease), background .5s var(--ab-ease),
        color .5s var(--ab-ease), box-shadow .5s var(--ab-ease);
}

#compliance .cmp__seal svg {
    width: 16px;
    height: 16px;
}

#compliance .cmp__no {
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 200;
    font-size: 22px;
    line-height: 1;
    color: rgba(11, 31, 51, .16);
    transition: color .5s var(--ab-ease);
}

/* --- 9.2 the standard --------------------------------------------------- */

#compliance .cmp__k {
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 500;
    font-size: 28px;
    line-height: 1.05;
    letter-spacing: .2px;
    /* #1195cf measures 3.4:1 here; this is 5.6:1 */
    color: #0b6d97;
    transform: translateZ(26px);
    transition: transform .5s var(--ab-ease), color .5s var(--ab-ease);
}

#compliance .cmp__tag {
    margin: 10px 0 12px;
    padding: 4px 10px;
    border-radius: 999px;
    background: rgba(34, 179, 230, .1);
    border: 1px solid rgba(34, 179, 230, .2);
    font-family: var(--font-display, "Oswald", sans-serif);
    font-size: 9.5px;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: #12496b;
    transform: translateZ(18px);
    transition: transform .5s var(--ab-ease), background .5s var(--ab-ease),
        border-color .5s var(--ab-ease), color .5s var(--ab-ease);
}

#compliance .cmp__v {
    font-size: 13px;
    line-height: 1.62;
    color: var(--ab-body);
    transform: translateZ(8px);
    transition: transform .5s var(--ab-ease);
}

/* --- 9.3 hover ---------------------------------------------------------- */

#compliance .cmp:hover {
    border-color: rgba(34, 179, 230, .42);
    box-shadow: var(--ab-lift);
    background: linear-gradient(178deg, #ffffff 0%, #eef8fd 100%);
}

#compliance .cmp:hover .cmp__no {
    color: rgba(240, 165, 0, .5);
}

/* the plate stays put — data-mrnp-tilt owns its movement and writes an inline
   transform a CSS one here would fight — and the contents come off its face */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {

    #compliance .cmp:hover .cmp__head {
        transform: translateZ(40px);
    }

    #compliance .cmp:hover .cmp__k {
        transform: translateZ(56px);
    }

    #compliance .cmp:hover .cmp__tag {
        transform: translateZ(38px);
    }

    #compliance .cmp:hover .cmp__v {
        transform: translateZ(18px);
    }

    #compliance .cmp:hover .cmp__seal {
        transform: scale(1.08);
    }
}

/* the seal and the tag are the affordance, and they answer without moving */
#compliance .cmp:hover .cmp__seal {
    background: var(--ab-gold);
    border-color: rgba(240, 165, 0, .55);
    color: #07182e;
    box-shadow: 0 12px 22px -10px rgba(240, 165, 0, .6);
}

#compliance .cmp:hover .cmp__tag {
    background: rgba(34, 179, 230, .18);
    border-color: rgba(34, 179, 230, .42);
    color: #0b4a6d;
}

/* ==========================================================================
   11. #units, #testimonials, #creds
   ========================================================================== */

/* --- #units — the two companies, set as berth plates ---------------------
   BEFORE
     Two identical stacked cards: a 210px photo band, a 62px ghost numeral in
     the seam, three paragraphs, a gold pill, a two-cell stat footer. Four
     things were wrong with it, and only one of them was taste.

     1. THE PHOTOGRAPH WAS MUD. index-theme.css:7541 lays a flat navy wash
        over it from 32% down to solid #0a2340, on top of a
        saturate(.72) brightness(.92) grade. Two aerials of a working yard
        came out as brown gravel — present, but carrying no information.

     2. THE STAT BAND WAS BROKEN, not merely plain. index-theme.css:7612
        sizes every span in the band as an 11px uppercase grey label. The
        ships figure is `<strong><span data-count="37">`, so that rule reached
        inside the strong and drew the number as a label: 37 and 36 rendered
        11px and grey beside a 30px white 1994. The two halves of one band
        were set in two different type sizes, which is why the row read as a
        mistake rather than as data.

     3. THE BUTTONS DID NOT LINE UP. Card 02's copy is three lines shorter
        than card 01's, and the grid stretches both cards to the same height,
        so the slack collected as a hole between 02's button and its stat
        band.

     4. THE 3D WAS DEAD. The markup carried `d3-card edge-sweep` on one
        element. .edge-sweep sets `isolation: isolate` and .abt-unit sets
        `overflow: hidden` — both grouping properties, so the used
        transform-style was flat and every translateZ() this section declared
        moved nothing. Section 9 documents that exact trap and says not to put
        .edge-sweep on a .d3-card; this section was doing it anyway.

   AFTER
     `d3-card` came off the markup and the translateZ() rules came out with
     it. The sweep is the one of the two that was actually rendering, and a
     card that has to clip a photograph cannot hold a 3D context anyway. The
     tilt is unaffected: data-mrn-tilt writes an inline transform on the card
     itself and only needs `perspective` on .abt-units, which .d3-stage
     supplies.

     What replaces it is flatter and louder — the photograph graded to read
     instead of veiled, the ghost numeral promoted to a machined UNIT chip on
     the image, the name given the banner's cyan-into-amber rule, the buttons
     bottom-aligned, and the stat band rebuilt as two readouts with the ships
     figure in cyan and the year in white.
   ------------------------------------------------------------------------ */

#units .abt-units {
    gap: 40px;
    perspective: 1500px;
    align-items: stretch;
}

#units .abt-unit {
    position: relative;
    display: flex;
    flex-direction: column;
    border-radius: var(--ab-r);
    overflow: hidden;
    background: var(--ab-card-dark);
    border: var(--ab-ring-dark);
    box-shadow: var(--ab-lift-dark);
    transition: box-shadow .6s var(--ab-ease), border-color .6s var(--ab-ease);
}

#units .abt-unit:hover {
    border-color: rgba(53, 198, 244, .45);
    box-shadow: 0 44px 80px -30px rgba(34, 179, 230, .48);
}

/* --- the photograph ---------------------------------------------------- */

#units .abt-unit__media {
    height: 250px;
}

/* Cooled a few degrees and handed back its contrast. These are flat, slightly
   warm stock aerials; graded this way they read as a surveyed site, which is
   the move the banner makes in section 5. */
#units .abt-unit__media img {
    filter: saturate(.92) contrast(1.16) brightness(.84) hue-rotate(-8deg);
    transform: scale(1.06);
    transition: filter .9s var(--ab-ease), transform 1.3s var(--ab-ease);
}

#units .abt-unit:hover .abt-unit__media img {
    filter: saturate(1.06) contrast(1.1) brightness(1);
    transform: scale(1.12);
}

/* Replaces the flat wash. The top two thirds stay open so the yard is
   actually visible; it closes only at the very bottom, where the plate has to
   take over. The survey grid is the banner's, at card scale — it is what
   stops a soft aerial from reading as a soft aerial. */
#units .abt-unit__media::after {
    background:
        repeating-linear-gradient(to right, rgba(53, 198, 244, .07) 0 1px, transparent 1px 54px),
        repeating-linear-gradient(to bottom, rgba(53, 198, 244, .07) 0 1px, transparent 1px 54px),
        linear-gradient(180deg,
            rgba(4, 18, 31, .60) 0%,
            rgba(4, 18, 31, .10) 34%,
            rgba(5, 22, 37, .44) 74%,
            rgba(7, 26, 46, .96) 100%),
        radial-gradient(120% 88% at 50% 0%, rgba(34, 179, 230, .18), transparent 64%);
}

/* .abt-unit carries data-mrn-tilt, which js/page-fx.js's blocked() skips, so
   nothing ever stamps it with .sg-shown — this waterline is drawn at rest and
   brightens on approach rather than growing from zero and never arriving.
   Cyan into amber, so the seam quotes the banner rule rather than inventing a
   third accent. */
#units .abt-unit__media::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    height: 3px;
    background: linear-gradient(90deg,
        var(--cyan-bright) 0%,
        rgba(53, 198, 244, .38) 58%,
        var(--gold, #ffad18) 100%);
    opacity: .55;
    transition: opacity .7s var(--ab-ease);
}

#units .abt-unit:hover .abt-unit__media::before {
    opacity: 1;
}

/* --- the index, as a chip rather than a ghost -------------------------- */

/* index-theme.css:7555 draws this as a 62px numeral at 10% white sitting in
   the seam between the photograph and the copy — too faint to read as a label
   and too large to ignore. Same element, same aria-hidden, promoted to a
   machined chip in the corner of the image and built to match .mrnp-crumb in
   the banner. */
#units .abt-unit__no {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 4;
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    border: 1px solid rgba(53, 198, 244, .30);
    border-left: 2px solid var(--cyan-bright);
    border-radius: 2px;
    background: rgba(6, 22, 38, .58);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 2.4px;
    color: #e2eef9;
    transition: border-color .5s var(--ab-ease), background .5s var(--ab-ease);
}

#units .abt-unit__no::before {
    content: "UNIT";
    color: rgba(167, 187, 207, .72);
}

#units .abt-unit:hover .abt-unit__no {
    border-color: rgba(53, 198, 244, .5);
    border-left-color: var(--gold, #ffad18);
    background: rgba(6, 22, 38, .72);
}

/* --- the copy ---------------------------------------------------------- */

/* flex:1 is what lets the button bottom-align. The body has to be the thing
   that absorbs the grid's slack, or the slack collects between the body and
   the stat band instead and shows up as a hole in the shorter card. The
   -46px pull index-theme.css:7551 sets is gone along with the ghost numeral
   it was tucking under the photograph. */
#units .abt-unit__body {
    flex: 1;
    display: flex;
    flex-direction: column;
    /* index-theme.css:7548 makes this relative so the -46px pull could sit
       above the media scrim on z-index 2. Both are gone, and while it stayed
       relative it was the containing block for the absolutely positioned UNIT
       chip below — which put the chip 16px inside the copy, on top of the
       company name, instead of 16px inside the card, on the photograph. */
    position: static;
    margin-top: 0;
    padding: 26px 30px 28px;
}

#units .abt-unit__body h3 {
    margin-bottom: 0;
    font-weight: 600;
    letter-spacing: .2px;
}

#units .abt-unit__body h3::after {
    content: "";
    display: block;
    width: 78px;
    height: 3px;
    margin: 16px 0 18px;
    background: linear-gradient(90deg, var(--cyan-bright), var(--gold, #ffad18));
    transition: width .6s var(--ab-ease);
}

#units .abt-unit:hover .abt-unit__body h3::after {
    width: 118px;
}

#units .abt-unit__body p {
    color: #b6cadd;
}

#units .abt-unit__body .mrn-btn {
    align-self: flex-start;
    margin-top: auto;
    border-radius: 999px;
}

/* --- the stat band ----------------------------------------------------- */

#units .abt-unit__meta {
    border-top: 1px solid rgba(53, 198, 244, .16);
    background: linear-gradient(180deg, rgba(53, 198, 244, .055), transparent 72%);
}

#units .abt-unit__meta > div {
    padding: 18px 30px 20px;
    gap: 6px;
}

#units .abt-unit__meta > div:first-child {
    border-right: 1px solid rgba(53, 198, 244, .16);
}

#units .abt-unit__meta strong {
    font-size: 34px;
    font-weight: 200;
    color: #fff;
}

/* index-theme.css:7612 sizes every span in this band as an 11px uppercase
   grey label — and the ships figure is a `<span data-count>` nested inside
   its own <strong>, so the label rule reached in and drew the number as a
   label. 37 and 36 came out 11px and grey next to a 30px white 1994, which is
   why one half of the band looked broken. Put back, one level deeper. */
#units .abt-unit__meta strong span {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: none;
}

/* the count is the figure that moves; the year is a constant. Colouring them
   apart is what makes the pair read as two kinds of fact rather than two
   numbers. */
#units .abt-unit__meta > div:first-child strong {
    color: var(--cyan-bright);
}

/* --- #testimonials — the remarks, set as inspection records --------------
   Before: four white boxes of italic 15.5px grey. The avatar disc was the
   worst of it — #fff on #1195cf is 3.4:1, so at 17px the initials read as
   empty circles.

   The first rebuild put the quote first and pinned the attribution to the
   bottom with `margin: 0 0 auto`. With equal-height plates and remarks of 3
   and 4 lines that opened a hole in the MIDDLE of the short cards, between
   the text and the rule, and left the index and the quote mark floating in
   opposite corners with nothing tying them to anything. Measured: 111px of
   text in a 280px plate.

   So the record now reads top-down the way a log entry does — who said it,
   a rule, then what they said. The quote mark stops being a corner ornament
   and becomes a hanging mark against the remark it belongs to, and any
   slack from a short remark falls at the foot of the plate where it reads
   as margin rather than as a gap. */

#testimonials .tst-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    align-items: stretch;
    gap: 26px;
    margin-top: 52px;
}

#testimonials .tst {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 28px 32px 30px;
    border-radius: var(--ab-r);
    background: linear-gradient(178deg, #ffffff 0%, #f4fafd 100%);
    border: var(--ab-ring);
    box-shadow: var(--ab-soft);
    transition: box-shadow .5s var(--ab-ease), border-color .5s var(--ab-ease),
        background .5s var(--ab-ease);

    /* the 3D room. No overflow / isolation / opacity / filter may be added
       here — each is a grouping property and flattens every translateZ. */
    perspective: 1100px;
    perspective-origin: 50% 44%;
    transform-style: preserve-3d;
}

/* --- the head: who recorded it ------------------------------------------ */

#testimonials .tst__head {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    margin-bottom: 18px;
    transform: translateZ(24px);
    transition: transform .5s var(--ab-ease);
}

#testimonials .tst__mono {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    border-radius: 13px;
    background: var(--ab-card-dark);
    border: 1px solid rgba(53, 198, 244, .28);
    /* 9.4:1 — the old disc was #fff on #1195cf, 3.4:1 */
    color: #6fd3f7;
    font-family: var(--font-display, "Oswald", sans-serif);
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 1px;
    transition: transform .5s var(--ab-ease), box-shadow .5s var(--ab-ease),
        border-color .5s var(--ab-ease), color .5s var(--ab-ease);
}

#testimonials .tst__who {
    flex: 1 1 auto;
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 500;
    font-size: 14.5px;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    line-height: 1.35;
    color: var(--ab-ink);
}

#testimonials .tst__no {
    flex: 0 0 auto;
    align-self: flex-start;
    font-family: var(--font-display, "Oswald", sans-serif);
    font-weight: 200;
    font-size: 20px;
    line-height: 1;
    letter-spacing: 1px;
    color: rgba(11, 31, 51, .3);
    transition: color .5s var(--ab-ease);
}

#testimonials .tst__rule {
    display: block;
    width: 100%;
    height: 1px;
    margin-bottom: 20px;
    background: linear-gradient(90deg, rgba(34, 179, 230, .38), rgba(11, 31, 51, .07) 60%, transparent);
    transform: translateZ(10px);
}

/* --- the remark --------------------------------------------------------- */

#testimonials .tst__text {
    position: relative;
    margin: 0;
    padding-left: 34px;
    /* reading size, upright, in ink — the italic light grey was the problem */
    font-size: 16.5px;
    line-height: 1.72;
    font-style: normal;
    color: var(--ab-ink);
    transform: translateZ(14px);
    transition: transform .5s var(--ab-ease);
}

/* the mark hangs against the remark instead of floating in a corner */
#testimonials .tst__text::before {
    content: "\201C";
    position: absolute;
    left: -2px;
    top: -14px;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 58px;
    line-height: 1;
    color: rgba(34, 179, 230, .28);
    transition: color .5s var(--ab-ease);
}

/* --- hover -------------------------------------------------------------- */

#testimonials .tst:hover {
    border-color: rgba(34, 179, 230, .42);
    box-shadow: var(--ab-lift);
    background: linear-gradient(178deg, #ffffff 0%, #eef8fd 100%);
}

/* the affordance that survives reduced motion */
#testimonials .tst:hover .tst__text::before {
    color: rgba(240, 165, 0, .55);
}

#testimonials .tst:hover .tst__no {
    color: rgba(240, 165, 0, .72);
}

#testimonials .tst:hover .tst__mono {
    border-color: rgba(240, 165, 0, .5);
    color: #ffc94d;
    box-shadow: 0 16px 26px -12px rgba(4, 18, 31, .55);
}

/* the plate itself never transforms — data-mrnp-tilt writes an inline
   transform and a CSS one here would fight it every frame. The head sits
   nearest the plate's perspective origin, so it carries the deepest lift
   without overrunning the edge; the remark, which reaches the corners, does
   not. */
/* The reduced-motion condition is gone from this one block on purpose. It
   is the hover depth for .tst — the contents standing off the card face is
   the whole point of the tilt, and the tilt itself is no longer gated (see
   js/marine.js initTilt). Gating the depth but not the rotation would leave
   the card turning as a flat slab, which is the worst of both.

   The other three no-preference blocks in this file — #profile .mrnp-strip,
   #vision .viz-card, #compliance .cmp — are deliberately left alone. The
   strip is not a card, and the viz-card and cmp depth is dead code either
   way: both are flattened by their own overflow/filter, per section 9. */
@media (hover: hover) {

    #testimonials .tst:hover .tst__head {
        transform: translateZ(46px);
    }

    #testimonials .tst:hover .tst__text {
        transform: translateZ(24px);
    }

    #testimonials .tst:hover .tst__mono {
        transform: scale(1.06);
    }
}

#creds .mrnp-certcard {
    border-radius: var(--ab-r-panel);
    box-shadow: var(--ab-soft);
    overflow: hidden;
}

#creds .mrnp-certcard:hover {
    box-shadow: var(--ab-lift);
}

#creds .abt-cred-cta .mrn-btn {
    border-radius: 999px;
    padding: 18px 32px;
}

/* ==========================================================================
   12. 3D ON EVERY SECTION
   ==========================================================================
   js/marine-pages.js initTilt3d() drives [data-mrnp-tilt]: on mousemove it
   writes `perspective(1000px) rotateY() rotateX() translateY(-6px)` inline
   from the pointer position, and clears it on mouseleave. It opts out on
   coarse pointers and under reduced motion by itself, so there is nothing to
   guard here.

   Six card groups already carried it. The heritage dates, the compliance
   stamps and the auditors' quotes did not, which is why only part of the page
   answered the pointer. They carry it now — 21 tilt-enabled cards.

   TWO THINGS THAT MATTER:

   - The inline transform beats any CSS `transform`, so a `:hover { transform:
      translateY(...) }` on a tilted card is dead the moment the pointer moves
      and fights it on the way out. Those are removed below; the tilt's own
      translateY(-6px) is the lift, and hover keeps only shadow and border.
   - A rotation reveals nothing unless the contents stand off the face. Each
      tilted card gets preserve-3d and its children get translateZ, so the
      numeral, the heading and the body sit on three different planes.
   ========================================================================== */

#heritage .abt-time__item,
#compliance .cmp,
#testimonials .tst {
    transform-style: preserve-3d;
    will-change: transform;
}

/* hover keeps the material change; the tilt owns the movement */
#heritage .abt-time__item:hover,
#compliance .cmp:hover,
#testimonials .tst:hover {
    transform: none;
}

/* --- depth for the tilt to reveal --------------------------------------- */
#heritage .abt-time__year { transform: translateZ(26px); }
#heritage .abt-time__item h4 { transform: translateZ(16px); }
#heritage .abt-time__item p { transform: translateZ(6px); }




#creds .mrnp-certcard { transform-style: preserve-3d; }
#creds .mrnp-certcard__bar { transform: translateZ(18px); }

/* the profile photograph and its caption sit on different planes too */
#profile .abt-split__media { transform-style: preserve-3d; }
#profile .abt-frame__cap { transform: translateZ(30px); }

/* ==========================================================================
   13. WHICH CLASS THE SCROLL STATES HANG OFF
   ==========================================================================
   These blocks carry data-mrn-reveal + data-mrn-stagger in the markup, so
   `.mrn-in` looks like the hook. It never arrives. js/page-fx.js runs an
   auto-choreography pass over every inner page that moves elements from
   marine.js's engine to index-motion.js's: it stamps data-sg-in on the child,
   strips data-mrn-reveal from it (page-fx.js:104), then releases the parent
   container's data-mrn-reveal and data-mrn-stagger (page-fx.js:121-122) so
   exactly one engine owns each element. Measured on this page: 5 elements end
   with .mrn-in, 45 with .sg-shown, and none of the containers has either.

   So anything that must appear on scroll keys on `.sg-shown`, which
   index-motion.js leaves behind permanently once an entrance finishes — see
   the rules in sections 6 and 8. That also removes the need for hand-set
   nth-child delays: the reveal engine already staggers the items, so each rule
   simply follows its own card in.
   ========================================================================== */

/* ==========================================================================
   14. RESPONSIVE
   ========================================================================== */

@media (max-width: 1100px) {

    #heritage .abt-time {
        grid-template-columns: repeat(2, 1fr);
    }

    #vision .viz__stage {
        margin-top: -96px;
        gap: 22px;
    }

    /* the #compliance id outranks index-theme.css:7584's own breakpoints, so
       this file has to restate every step down */
    #compliance .abt-comply {
        grid-template-columns: repeat(3, 1fr);
    }

    #vision .viz-card {
        padding: 34px 28px 32px;
    }

    #profile .mrnp-strip strong {
        font-size: clamp(32px, 4.4vw, 42px);
    }
}

@media (max-width: 860px) {

    /* --- the banner (section 5) ---------------------------------------- */

    /* The crop inverts here. A 3:2 frame inside a box that is taller than it
       is wide keeps roughly the middle third of the width and nothing else,
       so the choice is which third — and the lit one is worth more than the
       geometric centre. */
    .abt-hero .mrnp-hero__bg {
        background-position: 58% 38%;
    }

    /* Section 5's horizontal grade assumes the copy holds the left third of
       the frame. Below 860 it holds all of it, so the wash goes back to being
       broadly even — but no heavier than it has to be. Matching the desktop
       weight across the whole width buried the photograph: at this size the
       lit quay is a strip a finger wide, and darkening it to seat the text
       leaves a navy rectangle where the picture was. */
    .abt-hero .mrnp-hero__scrim {
        background:
            linear-gradient(180deg,
                rgba(4, 18, 31, .78) 0%,
                rgba(4, 18, 31, .34) 30%,
                rgba(4, 18, 31, .54) 62%,
                rgba(4, 18, 31, .94) 100%),
            linear-gradient(96deg,
                rgba(5, 22, 37, .44) 0%,
                rgba(5, 22, 37, .20) 100%);
    }

    /* the bloom is pulled back to match — it was sized against a frame with
       three times this much width showing */
    .abt-hero::before {
        opacity: .66;
    }

    .abt-hero .mrnp-hero__orb--b {
        width: 240px;
        height: 200px;
        right: 4%;
        bottom: 30%;
    }

    #profile .abt-split {
        gap: 44px;
    }

    #profile .mrnp-strip {
        margin-top: 48px;
        padding: 28px 16px;
    }

    /* two-up on a phone, so only the left column keeps a divider */
    #profile .mrnp-strip {
        grid-template-columns: repeat(2, 1fr);
        gap: 8px;
    }

    #profile .mrnp-strip > div,
    #profile .mrnp-strip > div:nth-child(2n) {
        border-right: 0;
        padding: 18px 10px;
    }

    #profile .mrnp-strip > div:nth-child(odd) {
        border-right: 1px solid rgba(11, 31, 51, .09);
    }

    /* a 21:9 band is a 40px sliver on a phone */
    #vision .viz__band img {
        aspect-ratio: 4 / 3;
    }

    /* one column, and the plates stop overlapping the band — at this width
       the overlap would bury most of the photograph */
    #vision .viz__stage {
        grid-template-columns: 1fr;
        gap: 18px;
        margin-top: -48px;
    }

    #vision .viz-card {
        padding: 30px 24px 28px;
    }

    #vision .viz-card__no {
        font-size: 42px;
        top: 20px;
        right: 22px;
    }

    #heritage .abt-time {
        grid-template-columns: 1fr;
        gap: 20px;
    }

    #compliance .abt-comply {
        grid-template-columns: repeat(2, 1fr);
        gap: 12px;
    }

    /* .tst-grid no longer inherits .mrnp-quotes' breakpoints
       (marine-pages.css:1476), so it carries its own */
    #testimonials .tst-grid {
        grid-template-columns: 1fr;
        gap: 16px;
    }

    #testimonials .tst {
        padding: 26px 22px 24px;
    }

    #testimonials .tst__text {
        padding-left: 28px;
        font-size: 15.5px;
    }

    #testimonials .tst__text::before {
        font-size: 48px;
        top: -10px;
    }

    #compliance .cmp {
        padding: 18px 16px 20px;
    }

    #compliance .cmp__k {
        font-size: 24px;
    }

    #units .abt-units {
        gap: 30px;
    }

    /* Section 11 sets these with an id, so index-theme.css's own phone steps
       (7666, 7670) can no longer reach them — they have to be restated here
       or the card keeps its 30px desktop gutters on a 375px screen. The photo
       comes down with them: at one card per row a 250px band is most of the
       first screenful and the name gets pushed under the fold. */
    #units .abt-unit__media {
        height: 200px;
    }

    #units .abt-unit__body {
        padding: 22px 22px 24px;
    }

    #units .abt-unit__meta > div {
        padding: 15px 22px 17px;
    }

    #units .abt-unit__meta strong {
        font-size: 29px;
    }

    #units .abt-unit__no {
        top: 13px;
        left: 13px;
    }

    /* real 3D only ever shows the first frame of a hover that never arrives.
       #units is no longer in this list: section 11 stopped declaring
       translateZ() altogether once it came out that .edge-sweep and
       overflow:hidden were flattening the card anyway. */
    #heritage .abt-time__year,
    #heritage .abt-time__item h4,
    #heritage .abt-time__item p,
    #compliance .cmp__head,
    #compliance .cmp__k,
    #compliance .cmp__tag,
    #compliance .cmp__v,
    #testimonials .tst__head,
    #testimonials .tst__text,
    #testimonials .tst__rule,
    #creds .mrnp-certcard__bar,
    #profile .abt-frame__cap,
    #vision .viz-card__no,
    #vision .viz-card__icon,
    #vision .viz-card h3,
    #vision .viz-card__seam,
    #vision .viz-card__lead,
    #vision .viz-card__body {
        transform: none;
    }
}

/* ==========================================================================
   15. REDUCED MOTION
   Material stays, movement goes. The second rule matters most: the heading
   rules and stamp bars are authored at scaleX(0), so switching the transition
   off is not enough — without forcing them to `none`, which is identity, they
   would sit at zero for ever and the page would look unfinished.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

    #profile .abt-frame,
    #profile .abt-frame img,
    #profile .abt-split__body .mrn-btn,
    #heritage .abt-time__item,
    #vision .viz-card,
    #compliance .cmp,
    #units .abt-unit,
    #units .abt-unit__media img,
    #testimonials .tst,
    #creds .mrnp-certcard {
        transition: none !important;
        transform: none !important;
    }

    #heritage .abt-time__item::before,
    #heritage .abt-time__item.sg-shown::before,
    #compliance .cmp__rule {
        transform: none !important;
        transition: none !important;
    }

    #units .abt-unit__media::before {
        opacity: 1 !important;
        transition: none !important;
    }
}
