
  /* ============================================================
     TYPE — own note, per explicit instruction: no shared heading
     custom properties exist anywhere in this codebase (checked every
     :root declaration in both index.html and branding.html before
     writing this file — only page-local sizing vars like
     --services-heading-size and branding's own --card-headline-size,
     nothing named for reuse across pages). So every size/weight below
     is set directly against the one shared font stack ('Aspekta
     Variable', 'DM Sans', sans-serif — used unconditionally
     everywhere in this file) rather than a token that doesn't exist,
     each one traced back in its own comment to the homepage rule it
     matches. If a real shared heading scale gets built later, this
     file is the one to update.

     Also per explicit instruction: the category and stat sections
     below carry no kicker label. The one exception is the hero
     panel's own small uppercase .hero-panel__label, added by
     later explicit request — see that section's own comment.
  ============================================================ */

  /* ============================================================
     SEAFOOD HERO — own build. Same two-layer masked-aperture
     mechanic as the homepage hero (a base layer + a full duplicate
     "reveal" layer, clipped to the flame-hand silhouette via the same
     PNG mask asset, mask-position/size driven per-frame by JS toward
     the pointer), deliberately NOT wired to the homepage's own
     #hero/#heroReveal/FLAME_MASK_CONFIG machinery — own IDs throughout
     (seafoodHero/seafoodReveal/etc.) so the shared bundle's own hero
     script, which looks up id="hero" unconditionally, simply finds
     nothing here and never touches this page's markup.

     Per explicit follow-up request, this DOES now reuse the
     homepage's own scroll-pin-and-grow choreography (own
     .seafood-hero-pin-wrapper, same calc(100svh + 90vh) reserved
     scroll distance, same position:sticky hero) — see SEAFOOD_MASK
     below for the full growth math, ported from FLAME_MASK_CONFIG.
     Still NOT ported: the corner-icon handoff (this hero has no
     corner mark to peel off of) and desktop-only — mobile keeps its
     own simpler static strip, see the max-width:767px override below
     and SEAFOOD_MASK's own comment on why.
  ============================================================ */
  .seafood-hero-pin-wrapper{
    position: relative;
    height: calc(100svh + 90vh); /* 90vh matches the homepage's own FLAME_MASK_CONFIG.pinExtraVh — reserved extra scroll distance the growth animation plays out over before the page continues into the next section */
  }
  .reduce-motion .seafood-hero-pin-wrapper{ height: auto; } /* no pin under reduced motion — matches the homepage's own identical rule */
  .seafood-hero{
    position: sticky;
    top: 0;
    width: 100%;
    height: 100svh;
    min-height: 620px;
    overflow: hidden;
    background: var(--color-violet);
  }
  .reduce-motion .seafood-hero{ position: relative; }
  @media (max-width: 767px){
    /* mobile keeps its existing stacked, non-pinned layout (see the
       hero's own max-width:767px override further down) rather than
       the homepage's full-bleed pinned mobile hero — reconciling the
       two would mean rebuilding this page's whole mobile hero from
       scratch, which wasn't part of this request. */
    .seafood-hero-pin-wrapper{ height: auto; }
    .seafood-hero{ position: static; }
  }
  /* ---- base layer: violet ground. No dot-grid here on purpose — per
     explicit spec, only the REVEAL layer carries the fish; the base
     stays plain so hovering genuinely "discovers" them rather than
     them sitting visible in the background the whole time.

     Own removal, per explicit report ("the giant 'Seafood.' word in
     the lower left has to leave the first viewport"): there were TWO
     copies of this class's content — a persistent base-layer instance
     (id=seafoodHeadlineBase, always visible, never faded/masked,
     genuinely just decoration — confirmed by checking every rule
     touching this class: nothing ever hides or moves it) and a
     SEPARATE duplicate inside .seafood-hero__reveal, only visible
     through the roaming mask aperture and color-flipping with the
     growth state (own comment further down). Only the base instance
     was "the giant word in the lower left" the report describes — the
     reveal copy isn't a persistent lower-left element, it's small,
     roaming, and only glimpsed through the mask shape. So: the base
     <h1 id="seafoodHeadlineBase"> markup is deleted outright (not
     hidden via opacity/visibility, per explicit instruction), while
     this class and its reveal-layer duplicate stay — deleting the
     class itself would silently break the mask's own reveal content,
     which wasn't part of this request. This rule below now exists
     only to size/position that reveal-layer copy. ---- */
  .seafood-hero__headline{
    position: absolute;
    left: 4%;
    bottom: 8%;
    margin: 0;
    /* matches h1.headline's own family/weight (the homepage's heavy
       heading treatment, font-weight 650, Aspekta) — size is this
       file's own derivation, not a token: a single word needs a
       different clamp than the homepage's 3-stacked-line hero, so
       this is sized on its own terms (see TYPE note above). */
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 650;
    font-size: clamp(64px, 11vw, 200px);
    line-height: 0.92;
    letter-spacing: -0.01em;
    color: var(--color-cream);
    z-index: 5;
    pointer-events: none;
  }
  /* ---- headline + panel — NOT part of the aperture, always visible
     regardless of mask state. Deliberately plain text on the violet
     ground: no card/box, no monospace — the branding hero's panel
     treatment is explicitly off-limits for type here.

     Own follow-up, per explicit audit + instruction ("do not
     introduce any new font-size... every size must resolve to an
     existing sitewide token/class"): this file's own type audit
     found NO shared :root font-size tokens anywhere in the codebase —
     every page sizes type via clamp()s baked into each class. Per
     explicit direction after that audit: headline font-size/line-
     height/letter-spacing are UNCHANGED from the prior relayout
     (clamp(56px,5.6vw,96px) — no sitewide "H1 step" fits a wrapping
     multi-word headline; the homepage's only <h1> is a single-word-
     per-line mega-scale with no wrap support, explicitly rejected as
     a source here). What DID change: left/right now match the 6vw
     horizontal inset every other section on this page already uses
     (.seafood-category/.seafood-services/.seafood-cta) — the hero
     was the one outlier at 4%/5%, now consistent. */
  /* own follow-up (2026-09-29): the base + mobile rules that used to
     live here as .seafood-hero__panel-headline/.seafood-hero__panel/
     -row/-label/-body moved to the shared bundle (index.html) and were
     renamed to the page-agnostic .hero-panel/.hero-panel__headline/
     __row/__label/__body — branding.html reused these five rules
     verbatim (see its own former copy's comment), so they're no longer
     seafood-specific. This page's markup below now uses the shared
     classes; only the reveal-layer duplicate rules just below
     (seafood-only — branding has no reveal layer) stay here,
     referencing the new names. */
  /* ---- reveal layer — the inverted duplicate. Ground flips to
     cream (near-black on the homepage), fish + duplicate headline are
     ink. See the publish report for the exact contrast + why this
     pair, not the homepage's ink/violet pair.

     Own fix, per explicit report ("the font needs to inverse too...
     as the [aperture] gets bigger on scroll"): the persistent panel
     was cream-only, so once the growing aperture's cream ground
     spread under it, the panel read as cream-on-cream. Rather than
     approximate this with a scroll-progress crossfade, this
     duplicates the panel into the reveal layer exactly the way the
     headline is already duplicated — same classes, same position (both
     .seafood-hero and .seafood-hero__reveal share the same inset:0
     coordinate space), ink-colored — so it appears/disappears in
     lockstep with the ACTUAL mask shape, gap-for-gap, rather than a
     guess at when the aperture "should" have covered it. */
  .seafood-hero__reveal .hero-panel__headline,
  .seafood-hero__reveal .hero-panel__label,
  .seafood-hero__reveal .hero-panel__body{
    color: var(--color-near-black);
  }
  .seafood-hero__reveal{
    position: absolute;
    inset: 0;
    z-index: 8;
    overflow: hidden;
    background: var(--color-cream);
    pointer-events: none;
    mask-repeat: no-repeat;
    -webkit-mask-repeat: no-repeat;
    mask-image: url("https://cdn.prod.website-files.com/6aaab8aa5da02fa0b7406b4a/6ab4924a3fc9490cf2ae1f98_flame-hand-mask.png");
    -webkit-mask-image: url("https://cdn.prod.website-files.com/6aaab8aa5da02fa0b7406b4a/6ab4924a3fc9490cf2ae1f98_flame-hand-mask.png");
  }
  .seafood-hero__reveal .seafood-hero__headline{ color: var(--color-near-black); }
  /* own fix, per explicit request ("do white fish on black vs white
     on grey when the [aperture] scroll[s]"): the reveal's cream
     ground only applies pre-scroll (the hover-open state, where the
     ink fish/headline/panel pairing was originally spec'd and
     approved). Once scrolling drives the aperture's GROWTH phase, the
     SEAFOOD_MASK script now toggles this class, flipping the ground
     to near-black — matching the homepage's own ink-ground reveal
     convention — with the fish grid's white fill needing no change
     (already reads cleanly on black without its cream-legibility
     outline doing any real work there) but the duplicated headline
     and panel text, previously ink-on-cream, switched to cream-on-
     black so they don't go invisible against their own new ground. */
  .seafood-hero__reveal.is-growing{ background: var(--color-near-black); }
  .seafood-hero__reveal.is-growing .seafood-hero__headline{
    color: var(--color-cream);
  }
  /* own revert, per explicit follow-up ("remove the white box behind
     the paragraph font now on scroll"): the boxed cream-on-white
     treatment below is gone — panel-headline/label/body now match
     .seafood-hero__headline's own treatment just above, cream text
     directly on the near-black growth ground, no box. */
  .seafood-hero__reveal.is-growing .hero-panel__headline,
  .seafood-hero__reveal.is-growing .hero-panel__label,
  .seafood-hero__reveal.is-growing .hero-panel__body{
    color: var(--color-cream);
  }
  #seafoodHero.is-growing > .hero-panel,
  #seafoodHero.is-growing > .hero-panel__headline{ opacity: 0; }
  /* ---- fish dot-grid — the cherry-bomb tiling component, shape
     swapped for a hand-authored fish silhouette (no fish artwork
     exists anywhere in this codebase — see the publish report). Prior
     color history (ink@0.55 read grey, olive rejected, brand yellow
     rejected as "too crazy") landed on a plain white fill — see this
     file's own git history for that writeup, since none of it applies
     anymore after this rebuild.

     COLOR — own fix, per explicit report ("cream fish on ink... makes
     black and white the only two colors, exiles violet to a couple of
     corner slivers"): fill is now the brand violet (--color-violet,
     #7D63E4 as of 2026-09-30, was #7A5CFF) — 3.58:1 against ink
     (#252224), clears WCAG AA for large-scale decorative content with
     room to spare without shouting. Stroke stays ink (#252224,
     stroke-width 7 in the tile's own pre-scale units) — on ink ground
     it's functionally invisible (stroke color = ground color) but
     still holds each silhouette's edge crisp at the smallest scales
     the tiling below now uses, which matters more now that not every
     fish renders at the original single fixed size.

     TILING — own rebuild, per explicit report ("a perfectly even grid
     of identical fish... reads as wallpaper rather than a school"):
     replaces the old 62x124/2-fish tile with a 1056x1056 tile holding
     144 individually varied fish (plus edge-wrap duplicates so the
     tile still repeats seamlessly — see the generator script's own
     wrap-bbox check), each with its own:
       - scale, uniform in [0.55, 1.35] of the original fill size
       - rotation, uniform in [-24°, +24°]
       - position: cell grid offset half a cell per row (the same
         brick-stagger the original 2-fish tile already did, just
         scaled up), then jittered independently within its own cell
     Cell size (88x88, square) is picked so each fish's own territory
     is ~2x the original tile's per-fish area (3844px² → ~7688px²) —
     roughly half density, since varied sizes read as fuller per fish
     than the old uniform grid did. Opacity is NOT varied — every fish
     renders at full violet; an earlier mockup with faded fish read as
     grey and dirty rather than distant, so depth comes from scale
     alone, per explicit instruction.

     Generated once at build time by a seeded PRNG (seed 1337, see
     dev-scripts — not checked into this file, the OUTPUT is), not at
     runtime: this is a stronger guarantee than a seeded runtime RNG
     for "doesn't reshuffle on render or resize" — there is no runtime
     randomness to reshuffle, the pattern is baked into the asset.
     Same "static, no idle animation" contract as before: whatever
     apparent motion you see on scroll is the aperture window (or, at
     full growth, background-position) moving over this fixed pattern,
     not an animation on the fish themselves. */
  .seafood-hero__fish-grid{
    position: absolute;
    inset: 0;
    /* own change for /agencies: shape set by JS below (cherry-bomb
       tile, same component/mechanism as the homepage's own hero-reveal
       dot-grid — CHERRY_BOMB_SVG_TEMPLATE + window.PALETTE.violet, see
       that script's own comment), not a static CSS background-image.
       background-size matches the tile's own native 62x124 unit
       (the fish tile's old 1056x1056 was a pre-baked composite at a
       different shape's native size — this is the mechanical
       consequence of swapping in a differently-sized tile, not a new
       visual treatment). */
    background-size: 62px 124px;
    background-repeat: repeat;
    opacity: 1;
  }
  @media (max-width: 767px){
    .seafood-hero{ height: auto; min-height: 0; padding: 96px 6% 56px; }
    /* mobile: stack in DOM order (headline, label, paragraph),
       left-aligned, full width — the desktop bottom-row split and
       flex-to-bottom spacing are desktop-only, per explicit spec.
       (own cleanup: the old .seafood-hero__headline mobile override
       that lived here is gone along with that element itself — see
       this file's own note on the deleted "Seafood." decoration. Own
       follow-up (2026-09-29): the mobile overrides for .hero-panel and
       its four elements that used to live here moved to the shared
       bundle alongside their base rules — see this file's own note
       further up.) */
    .seafood-hero__reveal{ display: none; } /* see SEAFOOD_MASK script: touch gets a static open state instead of a full-bleed mask over stacked, static content */
    .seafood-hero__mobile-reveal{ display: block; }
  }
  .seafood-hero__mobile-reveal{ display: none; }

  /* ============================================================
     CATEGORY STATEMENT — ink ground, large cream paragraphs. Reuses
     the homepage's OWN service-row__para scale (font-weight 400,
     clamp(20px,2vw,34px), line-height 1.18) verbatim rather than
     inventing a new paragraph treatment, per instruction to consume
     existing patterns wherever one exists. No kicker.

     Own update: renders four paragraphs (AGENCIES_CONFIG.category.
     paragraphs is an array), all .seafood-category__text at the same
     size — no separate intro line/size (own revert: an earlier
     version added a smaller intro <p> above the paragraphs; dropped
     per explicit follow-up that the two-size treatment read as two
     disconnected arguments).

     WORD REVEAL — own port, per explicit request ("same fade in word
     animation on scroll as some of the copy on the home page"): the
     homepage's own statement-text "illuminate" effect
     (ILLUMINATE_CONFIG/buildStatementText/updateIllumination in
     index.html) already supports a mode:"word" path alongside its
     default per-letter mode — that's the one ported here, since
     multiple full paragraphs calls for word-granularity, not letter.
     Dropped from the port: mix-blend-mode:difference (there's nothing
     behind this section to blend against — no floating cards, unlike
     the homepage) and the highlight-color branch (no highlighted
     phrase here). Kept: the dim-to-bright color crossfade (near-black
     to cream — on this section's own near-black ground that reads
     exactly like a fade-in, words starting invisible against their
     own background and brightening into legibility) and the small
     upward lift, both scroll-scrubbed via the same per-item-window
     math, see SEAFOOD_CATEGORY_REVEAL in the script. */
  .seafood-category{
    background: var(--color-near-black);
    color: var(--color-cream);
    padding: 14vh 6vw;
  }
  .seafood-category__text{
    max-width: 1100px;
    margin: 0 0 0.9em;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: clamp(20px, 2vw, 34px);
    line-height: 1.3;
  }
  .seafood-category__text:last-child{ margin-bottom: 0; }
  .seafood-category__word{
    display: inline-block;
  }

  /* ============================================================
     SELECTED WORKS — own rebuild, per explicit request to emulate
     kargo.com's own "Curated at Scale / Media Intelligence / Creative
     Science / Unmatched Outcomes" pattern: a stack of full-bleed
     numbered panels in normal scroll flow (own replacement for the
     earlier pinned/scaling two-card sequence — that mechanic is gone
     entirely, no more scroll-progress math needed at all), each with
     a floating card (title + 0X number + one line of scope copy)
     bottom-left, plus a scroll-position dot rail on the right edge
     that highlights whichever panel is in view (IntersectionObserver,
     not a scroll-math computation — there's no per-frame animation
     here to drive).

     Own adaptation, not a literal copy: kargo.com's version is
     navy-on-white; this reuses the page's own cream/near-black palette
     so it reads as this site's own pattern, not a foreign one. Section
     insets match the rest of the page's own 6vw convention.
  ============================================================ */
  .seafood-works{
    background: var(--color-cream);
    color: var(--color-near-black);
    padding: 12vh 0 14vh;
  }
  .seafood-works__heading{
    margin: 0 0 6vh;
    padding: 0 6vw;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 800;
    font-size: clamp(32px, 4.2vw, 64px);
    line-height: 0.95;
  }
  /* own addition for /agencies (text-only trust list in place of the
     image-based works panels below — same type step as
     .seafood-category__text, this page's own body-copy declaration,
     just recolored for the light section this sits in). Pulled up
     under the heading in the same 6vh/6vw rhythm as .seafood-works__heading. */
  .seafood-works__subline{
    margin: -4vh 0 6vh;
    padding: 0 6vw;
    max-width: 640px;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: clamp(20px, 2vw, 34px);
    line-height: 1.3;
    color: color-mix(in srgb, var(--color-near-black) 70%, transparent);
  }
  /* own temporary addition for /agencies: .trust-list__name and the
     testimonial content classes below are AUTHORED in the shared
     bundle's source (index.html, same type-step-reuse rationale
     documented there) as genuine reusable variants, per instruction.
     But the live shared CSS this page links (hero-v2-app-v28.css) was
     built before that source change, so it doesn't contain them yet —
     shipping this page correctly today means carrying a working copy
     here too, until the next shared-bundle version bump picks up
     index.html's own copy. Remove this block then; it would be dead
     (overridden-by-nothing, identical values) — not a drift risk. */
  .trust-list{
    padding: 0 6vw;
    display: flex;
    flex-wrap: wrap;
    column-gap: 48px;
    row-gap: 16px;
  }
  .trust-list__name{
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 650;
    font-size: 24px;
    color: var(--color-near-black);
  }
  @media (max-width: 640px){
    .trust-list__name{ font-size: 20px; }
  }
  .seafood-testimonial__quote{
    margin: 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: clamp(20px, 1.8vw, 28px);
    line-height: 1.35;
    color: var(--color-near-black);
  }
  .seafood-testimonial__attribution{
    margin: 2vh 0 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 500;
    font-size: 14px;
    color: color-mix(in srgb, var(--color-near-black) 60%, transparent);
  }
  .works-stack{
    display: flex;
    align-items: flex-start;
    gap: 20px;
    padding: 0 6vw;
  }
  .works-stack__panels{
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8vh;
  }
  .works-panel{
    position: relative;
    display: block;
    height: 62vh;
    min-height: 420px;
    border-radius: 18px;
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    background: color-mix(in srgb, var(--color-cream) 88%, var(--color-near-black));
    /* own follow-up, per explicit report ("animation... not working like
       Kargo"): kargo.com's own panels fade/rise into view as each one
       is scrolled to, one-shot, same idea as this site's own .works-item
       reveal (homepage Work grid, branding cases row) — reused here at
       the same duration/easing rather than inventing a new one. Toggled
       by a dedicated IntersectionObserver below, separate from the dot
       rail's own observer (different threshold, different job). */
    opacity: 0;
    transform: translateY(40px);
    transition: opacity 0.8s cubic-bezier(.16,1,.3,1), transform 0.8s cubic-bezier(.16,1,.3,1);
  }
  .works-panel.is-in{
    opacity: 1;
    transform: translateY(0);
  }
  .works-panel__img{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1);
    transition: transform 0.6s cubic-bezier(.16,1,.3,1);
  }
  .works-panel:hover .works-panel__img{ transform: scale(1.03); }
  .works-panel__scrim{
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 55%;
    background: linear-gradient(to top, color-mix(in srgb, var(--color-near-black) 45%, transparent), transparent 100%);
    pointer-events: none;
  }
  .works-panel__card{
    position: absolute;
    left: 28px;
    bottom: 28px;
    right: 28px;
    max-width: 420px;
    background: var(--color-cream);
    border-radius: 12px;
    padding: 22px 24px;
  }
  .works-panel__card-top{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin: 0 0 8px;
  }
  .works-panel__title{
    margin: 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 800;
    font-size: clamp(22px, 2vw, 30px);
    line-height: 1.05;
  }
  .works-panel__number{
    flex: 0 0 auto;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 500;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: color-mix(in srgb, var(--color-near-black) 45%, transparent);
  }
  .works-panel__body{
    margin: 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: clamp(14px, 1.1vw, 16px);
    line-height: 1.5;
    color: color-mix(in srgb, var(--color-near-black) 75%, transparent);
  }
  .works-stack__dots{
    flex: 0 0 auto;
    position: sticky;
    top: 50vh;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .works-stack__dot{
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--color-near-black) 25%, transparent);
    transition: background 0.2s ease, transform 0.2s ease;
  }
  .works-stack__dot.is-active{
    background: var(--color-near-black);
    transform: scale(1.35);
  }
  @media (max-width: 768px){
    .works-stack{ flex-direction: column; }
    .works-stack__dots{ display: none; } /* the rail is a scroll-position affordance for a tall desktop stack; two stacked mobile cards don't need it */
    .works-panel{ height: 55vh; min-height: 340px; }
    .works-panel__card{ left: 16px; right: 16px; bottom: 16px; max-width: none; }
  }
  @media (prefers-reduced-motion: reduce){
    .works-panel{ opacity: 1; transform: none; transition: none; }
  }

  /* ============================================================
     SERVICES — six rows. Reuses the homepage's OWN .service-row /
     .service-row__number / .service-row__titlecol / .service-row__title
     / .service-row__subs / .service-row__para (all shared-bundle
     classes, same grid columns, same 1px divider, same type scale —
     none redefined here except .service-row__subs' own color, see its
     own comment below). Own fix, real bug report: subs were skipped
     originally, collapsing rows with short paragraphs to bare titles
     with no balance — now added per the homepage's own six-item lists.
     Doodle is still skipped (no doodle content exists for this page),
     so the paragraph column below stays widened into that freed space
     (the homepage's own para sits at grid-column 5/10, leaving 10/13
     for a doodle this page doesn't have).

     Own follow-up, per explicit request: flipped from the homepage's
     ink ground to cream/dark type. --services-number can no longer
     use the shared bundle's own default (var(--color-orange)) as-is —
     orange-on-cream measures 2.64:1, below even the 3:1 large-text
     floor — so this page sets its own darker "burnt orange" (#B33700,
     4.87:1 on cream) as its --services-number instead, close to brand
     orange in hue without failing contrast. See the publish report
     for the full before/after numbers.
  ============================================================ */
  .seafood-services{
    background: var(--color-cream);
    /* own fix, caught in local testing: .service-row__title and
       .service-row__para (both reused verbatim from the shared
       bundle) declare no color of their own — on the homepage they
       inherit it from .services{ color: var(--services-text,...) },
       a rule that only matches class="services". This section uses
       page-scoped class="seafood-services" instead, so that rule
       never applied. Setting color here directly (still via the same
       --services-text custom property this file already writes via
       JS, so there's still one place to change it) is what actually
       makes the inheritance work. */
    color: var(--services-text, var(--color-near-black));
    padding: 10vh 6vw 4vh;
  }
  .seafood-services__heading{
    margin: 0 0 2vh;
    padding-bottom: 4vh;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 800;
    font-size: clamp(32px, 4.2vw, 64px);
    line-height: 0.95;
    color: var(--color-near-black);
  }
  #seafoodServicesStage .service-row__para{ grid-column: 5 / 13; }
  /* ---- STACK/UNSTACK — own build, per explicit request ("ease/
     unstack and stack on scroll"): replaces the shared bundle's own
     one-shot .service-row.is-visible reveal (a fixed-duration fade
     that never reverses) with a continuously scroll-scrubbed
     transform, same technique as the homepage's own FILL block
     (per-row progress computed straight from getBoundingClientRect().top
     against two viewport-height thresholds, recomputed every scroll
     tick — a pure function of position, not an accumulator, so
     scrolling back up genuinely re-stacks a row instead of leaving it
     revealed). --stack-t (0 = stacked/tucked under the row above, 1 =
     fully unstacked into its resting position) is written per-row by
     the STACK script below; this rule just consumes it. ---- */
  #seafoodServicesStage .service-row{
    opacity: 1; transform: none; transition: none; /* overrides the shared bundle's own one-shot opacity:0/translateY(24px) + .is-visible transition — this page drives both continuously via --stack-t instead */
  }
  #seafoodServicesStage .service-row > *{
    opacity: calc(0.25 + var(--stack-t, 1) * 0.75);
    transform: translateY(calc((1 - var(--stack-t, 1)) * 56px)) scale(calc(0.97 + var(--stack-t, 1) * 0.03));
  }
  @media (prefers-reduced-motion: reduce){
    #seafoodServicesStage .service-row > *{ opacity: 1; transform: none; }
  }
  /* own fix, real bug report ("looks like shit"): the shared bundle's
     ACCORDION used to be gated to max-width:767px, so this page's own
     desktop 12-col grid (set up above/below) was never touched by it
     above that width — the fix just below only needed to cover mobile.
     A later change made the accordion apply at EVERY width instead
     (own explicit request, homepage-only in intent). This page still
     has no accordion at any width and was never updated for that — at
     desktop widths it was silently inheriting the accordion's
     .service-row{display:block} (killing the 12-col grid entirely,
     collapsing every row into normal block flow) and
     .service-row__para{max-height:0; overflow:hidden; padding-bottom:32px}
     (a box-sizing:border-box box where the 32px of padding alone
     exceeds the 0 max-height, so the browser renders a 32px-tall
     clipped sliver — just tall enough to show the top half of the
     paragraph's first line, sliced through the middle, instead of
     hiding it completely). Un-gating the mobile-only fix below to hold
     at every width, plus restoring the grid/number/title properties
     the accordion also touches, fixes both. */
  #seafoodServicesStage .service-row{
    display: grid;
    cursor: default; /* accordion sets pointer for its own click-to-expand — nothing here is clickable */
  }
  /* own fix, restored (2026-09-30): briefly deleted as redundant while
     the shared bundle's accordion was gated to max-width:767px (see
     git history for that short-lived comment) — but the accordion is
     back to applying at every width again (own explicit request,
     matching R/GA's own reference), so its plain .service-row{padding:0}
     is back to beating the shared base .service-row{padding:28px 0 96px}
     rule at every width via source order. This page's own
     #seafoodServicesStage .service-row{padding:24px 0 48px} (below)
     only covers max-width:991px, so above that this page needs its own
     desktop value restored directly — not a new number, the homepage's
     own base value. */
  #seafoodServicesStage .service-row{ padding: 28px 0 96px; }
  #seafoodServicesStage .service-row__number{ display: block; } /* accordion hides this, folding the number into .service-row__title::before instead — this page never uses that prefix, so the dedicated number cell needs to stay visible */
  #seafoodServicesStage .service-row__title::before{ content: none; } /* suppress the accordion's own duplicate "01 " prefix — this page already shows the number via .service-row__number above */
  #seafoodServicesStage .service-row__title{
    font-size: clamp(14px, 1vw, 17px); /* accordion bumps this to a much larger collapsed-header size (own request, homepage-only) — this page's title sits beside the number as a small label, not a tappable header */
    margin: 0 0 0.6em;
  }
  /* own fix, real bug report ("every .service-row__titlecol contains
     only the title and no sub-list"): this page's own row-build script
     never appended a .service-row__subs list, so the only thing
     driving each row's height was the paragraph — collapsing rows with
     short paragraphs to ~120px against a 34px-max paragraph. Sub-list
     color needs its own override same as --services-number above: the
     homepage's own default (--services-subs, a cream-tinted mix) is
     tuned for a dark ground, invisible-adjacent against this page's
     cream. Reused verbatim from .seafood-stat__source below — the only
     other muted-secondary-text-on-this-page's-cream value already in
     this file, not a new one. Also needs the SAME max-height/overflow
     reset .service-row__para already gets below: the accordion's own
     ungated .service-row__subs rule (index.html) sets max-height:0 +
     overflow:hidden as its permanent collapsed state (rows only expand
     via .is-expanded, which nothing on this page ever adds) — without
     this override the subs exist in the DOM (confirmed via live
     inspection) but render at zero height, invisible. Caught in the
     same live check that measured the row/paragraph numbers below. */
  #seafoodServicesStage .service-row__subs{
    color: color-mix(in srgb, var(--color-near-black) 60%, transparent);
    max-height: none;
    overflow: visible;
  }
  #seafoodServicesStage .service-row__para{
    max-height: none;
    overflow: visible;
    padding-bottom: 0;
  }
  @media (max-width: 991px){
    #seafoodServicesStage .service-row{ padding: 24px 0 48px; }
    #seafoodServicesStage .service-row{ grid-template-columns: 1fr; }
    #seafoodServicesStage .service-row__number,
    #seafoodServicesStage .service-row__titlecol,
    #seafoodServicesStage .service-row__para{ grid-column: 1 / -1; grid-row: auto; }
  }

  /* ============================================================
     STAT — own rebuild, per explicit request: rebuilt AGAIN to use
     the homepage's own #situations ("Process") scroll-pin mechanic
     instead of the timed shuffle from the previous pass — reused
     deliberately, not reinvented, after the user's own account of
     going four rounds on that section to learn its shape: scroll-
     driven means completion is guaranteed by construction, reverse
     scroll works for free, and nothing fights native scrolling.

     Structure mirrors #situations exactly: THIS section (.seafood-stat)
     is the scroll-spacer itself — JS inflates its height to
     100vh + extraPx. .seafood-stat__sticky is the pinned element, but
     it is NOT position:sticky — this site's shared bundle sets
     overflow-x:hidden on html/body, which per spec silently promotes
     overflow-y to auto too, and that breaks position:sticky (it locks
     to the body's own box instead of the real viewport). #situations
     works around this by toggling the sticky element's inline
     position between "" / "fixed" / "absolute" on every scroll tick
     instead — no position:sticky, no body{position:fixed}, no
     scroll-jacking: native scroll is never prevented, this only
     repositions one element in response to it. Same technique here.

     One deliberate difference from #situations: that section disables
     its whole pin below 1024px width (motionEnabled requires
     innerWidth >= 1024) and falls back to plain static scroll on
     mobile. This section keeps the pin at every width, including
     390px — per explicit instruction ("Mobile: same mechanic at
     390") — reduced motion is the only thing that turns it off.

     Four .seafood-stat__frame elements sit stacked in one CSS Grid
     cell (grid-area:1/1 — Grid auto-sizes the shared track to
     whichever frame is tallest). Unlike the old build, there's no
     .is-active class and no CSS transition on opacity: JS writes each
     frame's opacity directly, every tick, as a pure function of
     scroll progress — a transition here would fight the scroll
     itself, producing lag between where you are and what you see.
  ============================================================ */
  .seafood-stat{
    position: relative;
    height: 100vh;
  }
  .seafood-stat__sticky{
    position: relative; /* toggled to fixed/absolute by JS, see SEAFOOD_STAT_PIN */
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: var(--color-cream);
    color: var(--color-near-black);
    padding: 0 6vw;
  }
  .seafood-stat__stage{
    display: grid;
    max-width: 1100px;
    width: 100%;
    margin: 0 auto;
    --stat-scale: 0.8;
  }
  .seafood-stat__frame{
    grid-area: 1 / 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2vh;
    opacity: 0;
    pointer-events: none;
    /* own change for /agencies: this page's frame holds a quote +
       attribution (.seafood-testimonial__quote/__attribution, shared
       bundle), not a number + body sentence side by side — stacked
       column instead of seafood.html's baseline row. */
  }
  .seafood-stat__source{
    /* unused on this page (removed from the DOM in JS — attribution
       lives per-frame instead, see the testimonial build script) but
       left defined in case a future page reuses this section as an
       actual stat again. */
    max-width: 1100px;
    width: 100%;
    margin: 3vh auto 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 500;
    font-size: 14px;
    color: color-mix(in srgb, var(--color-near-black) 60%, transparent);
    /* own choice: visible throughout, not gated to the held stat —
       unlike the old timed build, scroll position can rest on any of
       the 4 stats indefinitely (this is scrubbed, not a one-way
       shuffle), and the citation line covers all four figures
       collectively, not just the last one. */
  }
  /* WAYFINDER — own addition, per explicit request: a pinned section
     with no progress indicator reads as a stuck page. Checked the
     homepage's #situations first (see this section's own JS comment
     for the removed "01/08" counter found there) — it has no reusable
     indicator today, so this is a fresh build, not a reuse. Four
     ticks, one per stat, left-aligned to the numeral's own left edge
     (same max-width/margin:auto box as .seafood-stat__stage). Opacity
     is written directly by JS per tick, same "no CSS transition"
     reasoning as the frames above — a transition here would lag one
     tick behind the scroll position it's supposed to be reporting. */
  .seafood-stat__ticks{
    display: flex;
    gap: 10px;
    max-width: 1100px;
    width: 100%;
    margin: 2vh auto 0;
  }
  .seafood-stat__tick{
    flex: 0 0 auto;
    width: 28px;
    height: 3px;
    border-radius: 2px;
    background: var(--color-near-black);
    opacity: 0.25; /* fallback pending state before JS's first tick */
  }
  /* own choice, not specified: side-by-side only holds down to tablet
     width — below 767px the numeral and a multi-line stat sentence
     competing for horizontal room gets cramped fast, so this page's
     established mobile pattern (stack what's side-by-side at desktop)
     applies here too. */
  @media (max-width: 767px){
    .seafood-stat__frame{ flex-direction: column; align-items: flex-start; gap: 0.2em; }
  }
  /* prefers-reduced-motion: belt-and-suspenders — SEAFOOD_STAT_PIN's
     own reduceMotion branch already resets height/position/opacity
     directly (see the script), this just guards against a flash of
     the pinned layout before JS runs. Ticks are hidden outright under
     reduced motion rather than left static-full: with no scroll-driven
     motion to wayfind through (the page shows stat 4 only, already
     landed), a wayfinder has nothing left to indicate. */
  @media (prefers-reduced-motion: reduce){
    .seafood-stat{ height: auto; }
    .seafood-stat__sticky{ position: static; height: auto; padding: 14vh 6vw; }
    .seafood-stat__ticks{ display: none; }
  }

  /* ============================================================
     CTA — violet ground. Same reasoning as STAT: no existing
     "headline + standalone email" section anywhere on the site (the
     only other hello@ links are small footer list items), so this is
     derived from the homepage heading treatment + a plain link. This
     section also stands in for the shared site footer, which
     /branding also omits entirely (confirmed live: no <footer>, no
     "To The Moon", no footer columns on that page) — so the small
     text line at the bottom is this page's own footer line, not the
     homepage's big shared one.
  ============================================================ */
  .seafood-cta{
    background: var(--color-violet);
    color: var(--color-cream);
    padding: 16vh 6vw 6vh;
    text-align: center;
  }
  .seafood-cta__headline{
    margin: 0 0 0.6em;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 700;
    font-size: clamp(36px, 5vw, 84px);
    line-height: 1.02;
    letter-spacing: -0.01em;
    color: var(--color-cream);
  }
  .seafood-cta__email{
    display: inline-block;
    margin: 0 0 10vh;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: clamp(24px, 2vw, 32px);
    color: var(--color-cream);
    text-decoration: underline;
    text-underline-offset: 0.15em;
  }
  .seafood-cta__footer{
    margin: 0 0 0.6em;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 500;
    font-size: 14px;
    /* own flag, not a fix: cream-on-violet at this size measures
       ~3.51:1 — under the 4.5:1 body-text floor. The 5-color palette
       has no higher-contrast option for static text on violet (yellow
       is motion-only, per its own comment in window.PALETTE). Kept
       small and quiet on purpose (a copyright-style credit line reads
       wrong blown up to the 24px floor used elsewhere on this page) —
       flagged here and in the publish report rather than silently
       shipped. */
    color: var(--color-cream);
  }
  /* ---- SOURCES — new, per explicit request: a citation line below
     the footer credit, body-copy weight (400, matching the page's own
     body-text weight rather than the footer line's 500) and reduced
     opacity so it reads as a quiet footnote, not a headline claim.
     Same underlying contrast ceiling as .seafood-cta__footer above
     (violet ground, no higher-contrast cream-family option in the
     palette) — deliberately pushed lower still by the requested
     reduced opacity, since a sources citation is expected to be the
     quietest text on the page, not body copy. Flagged, not a fix. */
  .seafood-cta__sources{
    margin: 0;
    font-family: 'Aspekta Variable', 'DM Sans', sans-serif;
    font-weight: 400;
    font-size: 13px;
    color: var(--color-cream);
    opacity: 0.55;
  }

  #headlineInner{ display: none; } /* shared-bundle compatibility shim — see branding.html's own identical comment for why this has to exist even though it's never shown */
