/* ===========================================================================
   CAN-Agri page furniture. `ca-` = site-specific.
   All [carry over] unless tagged otherwise.
   =========================================================================== */

/* ---- Header: a floating panel, measured off terminal-industries.com -----
   Jacqui's instruction 2026-09-08: floating with CTAs exactly as Terminal does
   it. Measured there at 1440: header fixed and transparent, the panel inside
   it rgba(0,0,0,.3) with blur(30px), 8px radius, 18px padding, 24px gap, and a
   three-slot CTA grid with 6px gaps whose labels are Geist Mono 11px/600 at
   1.5px tracking, uppercase. Translated onto our scale below. Nothing changes
   on scroll there and nothing changes here. D-87.

   visual-tells-approved:A17 A floating glass masthead is on the tells list and
   this file previously said so. It is now a deliberate, reference-driven choice
   by the design lead, not a default reached for. D-87 records the override. */
.ca-header {
  position: fixed; top: var(--ca-header-top); left: 0; right: 0; z-index: 100;
  background: transparent; border: 0;
  color: var(--ca-white);
  pointer-events: none;              /* the gutter beside the panel stays clickable */
}
.ca-header__in {
  pointer-events: auto; position: relative; overflow: visible;
  max-width: min(var(--ca-content-max), calc(100% - 2 * var(--ca-gutter)));
  margin-inline: auto;
  /* 12px, not 16 and not Terminal's 18. The panel height is driven by the
     LOCK-UP, not the buttons: the CTAs are 44 but the stacked lock-up needs 48
     to read, where Terminal's horizontal mark is only 26 tall. So their 18px
     padding gives a 78px panel and ours would give 84. 12px lands it at 72,
     tighter than Terminal, without shrinking the mark. This is the D-70
     horizontal-lock-up argument arriving a third time. */
  min-height: 0;
  padding: var(--ca-space-4) var(--ca-space-5) var(--ca-space-4) var(--ca-space-4);
  display: flex; align-items: center; justify-content: space-between; gap: var(--ca-space-5);
  border-radius: var(--ca-r-control);
  /* Alpha is set by MEASUREMENT, not by taste. The panel floats over white
     sections as well as the dark hero, and white 12px nav labels need 4.5:1
     against the worst case, which is the panel composited over white. Measured:
     .42 gives 2.48:1 and fails, .55 gives 3.52:1 and fails, .65 gives 4.72:1
     and .72 gives 5.87:1. Terminal runs .30 because their whole page is dark.
     axe passed all of these, because it cannot composite through alpha plus a
     backdrop-filter, so this one was computed by hand. See D-87.
     Jacqui asked for 5 percent less on 2026-09-08, so .72 became .67 and the
     no-backdrop-filter fallback .86 became .81. Recomputed by hand over white
     before applying: .67 gives 5.02:1 and .81 gives 7.85:1, both still clear of
     4.5:1. There is no room for another 5 percent after this: .62 lands at
     about 4.3:1 and fails. D-100. Jacqui asked for 10 percent less on
     2026-10-26; .60 measured 3.98:1 and fails, so the glass went to .65, 4.62:1,
     the lightest that still passes (D-289). */
  background: rgba(22, 48, 41, .81);
  /* Glass bevel. Three parts, each doing a different job: a hairline rim so the
     panel has an edge, an inset highlight along the top so light appears to
     catch it, and an inset shade along the bottom so it reads as a solid with
     thickness rather than a flat tint. The outer shadow lifts it off whatever
     is behind. One declaration, so it counts as one shadow. */
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .24),
    inset 0 -1px 0 rgba(22, 48, 41, .40),
    0 12px 32px rgba(22, 48, 41, .30);
}
@supports (backdrop-filter: blur(30px)) {
  /* saturate lifts what shows through, which is what makes it read as glass
     rather than as a grey wash */
  .ca-header__in { background: rgba(22, 48, 41, .65); backdrop-filter: blur(30px) saturate(140%); }   /* .67 to .65, D-289: white labels over white 4.62:1, the lightest that still passes */
}
@media (max-width: 767px) {
  /* The bar used to sit at 12 here. It cannot any more: the gable rises above
     it and 12px of clearance cut the mark by 9px. --ca-header-top is 52 on this
     breakpoint and the bar follows it, same as on desktop. */
  .ca-header { top: var(--ca-header-top); }
  /* The extra padding stays on desktop only. On mobile the bar is already
     taller than desktop, because the 48px menu button sets its height rather
     than the 44px CTAs, and adding 8px more left the gable rising just 4px:
     the whole straddle disappeared. Back to 12 here, which puts the rise at 13. */
  .ca-header__in { padding: var(--ca-space-3); gap: var(--ca-space-3); }
  /* the bar's foot now sits at 52 + 74 = 126px, so page heads clear --ca-header-clear */
  .ca-pagehead { padding-top: calc(var(--ca-header-clear) + var(--ca-space-5)); }
}
.ca-logo { display: inline-flex; align-items: center; text-decoration: none; }

/* THE LOCK-UP LEAVES THE BAR. Tim's idea, Jacqui's geometry (D-189).

   The 76px mark inside the bar pushed it to 102px, and 38 percent more masthead
   read heavy. So the mark comes OUT of the flow and straddles the bar instead:
   the bar's top edge falls just above the logotype, the gable rises clear, and
   the foot of the mark stays inside the bar. The bar goes back to the height the
   CTAs need, 70px, and the letters go UP to 18px.

   Three numbers, all off Jacqui's sketch and all measured back in the page:
     mark        114px desktop, 88px mobile
     foot        0.074 of the mark's height above the bar's bottom edge
     bar drops   the gable rises 52px, so the bar sits at 64px from the top,
                 not 24px, or the mark is cut by the viewport. At 24px it was
                 clipped by 28px, which is what Jacqui caught.

   THE BAR'S OFFSET IS NOW LOAD BEARING. Sticky cards, scroll padding and the
   menu's height all have to clear the bar, and the bar is no longer near the
   top of the screen. --ca-header-clear carries offset plus height; nothing
   should use --ca-header-h alone to mean "the space the bar takes".

   CONTRAST, HONESTLY. The gable now sits on the PAGE, not the glass, and the
   bar is fixed, so that ground is the hero, a white band or the dark contact
   band depending on scroll. Raw mark against ground: 2.44:1 over footage,
   1.54:1 over white, 9.18:1 over the contact band. The halo is what carries the
   first two, and a pixel test CANNOT SEE A SHADOW, which is the same lesson the
   hero headline taught in D-122. So the two low numbers are the unhaloed worst
   case, not the rendered result, and this stays a judgement call on the
   screenshots rather than a check that passes.

   Light variant everywhere: a dark mark reads beautifully above the bar and
   then vanishes against the glass below it, measured at 1.11:1. No single
   colour serves both halves, which is why the halo does the work instead. */
/* The mark sits the SAME distance from the bar's left edge as from its foot,
   and that distance is the bar's own padding, so its margin matches everything
   else inside the bar. It was 25px left against 9px below, which read as the
   mark sliding out of the bottom corner. */
.ca-logo { position: absolute; left: var(--ca-space-4); bottom: var(--ca-space-4); line-height: 0; z-index: 2; }
.ca-logo__mark {
  display: block; height: 103px; width: auto;   /* 114 less 10 percent, Jacqui 2026-09-22 */
  /* ONE thin hard shadow, no blur. The blurred pass under it read as a smudge
     and Jacqui rejected it. This is the same device as the hero headline, which
     carries 0 2px 0 with no blur over unpredictable footage (D-122): a hard
     edge reads as drawn, a soft one reads as a mistake. */
  filter: drop-shadow(0 1px 0 rgba(22, 48, 41, .92));
}
/* Mobile. 114 swamps a 358px bar and crowds the menu button, so the mark comes
   down to 88 and moves in to the smaller gutter. The bar sits at 52px rather
   than 64, because the gable only rises 40px at this size. Letters are 13.9px,
   still above the 12 Jacqui asked for. */
@media (max-width: 767px) {
  .ca-logo { left: var(--ca-space-3); bottom: var(--ca-space-3); }
  .ca-logo__mark { height: 79px; }
  .ca-nav { position: static; transform: none; }
}

/* Centred in the bar itself, not in the space left over beside the lock-up.
   Absolute, because the lock-up is out of the flow and the CTA cluster is not,
   so a flex centre would sit off to one side. */
.ca-nav { position: absolute; left: 50%; transform: translateX(-50%); }
.ca-nav__list { display: flex; align-items: center; gap: var(--ca-space-1); list-style: none; margin: 0; padding: 0; }
.ca-nav__link {
  display: block; padding: var(--ca-space-2) var(--ca-space-3);
  border-radius: var(--ca-r-control);
  color: var(--ca-white); text-decoration: none;
  font-family: var(--ca-font-label); font-size: var(--ca-size-caption);
  letter-spacing: var(--ca-track-eyebrow); text-transform: uppercase;
}
.ca-nav__link[aria-current="page"] { background: rgba(255,255,255,.14); }
@media (hover: hover) { .ca-nav__link:hover { background: rgba(255,255,255,.14); } }

/* The three-slot CTA cluster. Terminal runs three equal columns at 6px gaps
   with two-line uppercase mono labels; ours are the same shape on our scale.
   Tiers by ground, all carrying teal text: accent 10.69:1, white 14.11:1,
   tint 9.27:1. LABELS ARE PROVISIONAL and message-led, so they wait on the
   value-proposition session (Q-51). The three slots map onto the two primary
   audiences plus contact (D-81), which is what the shape is for. */
/* margin-left auto, because the lock-up is out of the flex flow now and
   space-between has nothing left to push these against. */
.ca-header__actions { display: flex; align-items: center; gap: var(--ca-space-3); margin-left: auto; }
.ca-cta-cluster { display: grid; grid-auto-flow: column; gap: var(--ca-space-3); }
/* The label STACKS, one word per line. Terminal does this with a span per word
   rather than by relying on a narrow container, which is why theirs breaks the
   same way at every width: measured there as two block spans at 11px/600,
   line-height 13.2px, so 1.2. Ours is looser at --ca-lh-lead, 1.5, because
   Jacqui asked for more space between the lines. Group the words in the markup
   to control where the break falls: "Invest" / "with us", not one word a line. */
.ca-cta {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  min-width: 104px; min-height: 44px; padding: var(--ca-space-2) var(--ca-space-4);
  border: 0; border-radius: var(--ca-r-control); text-decoration: none;
  font-family: var(--ca-font-label); font-size: var(--ca-size-btn);
  font-weight: var(--ca-weight-semibold); letter-spacing: var(--ca-track-eyebrow);
  text-transform: uppercase; color: var(--ca-teal);
  transition: background-color var(--ca-dur-fast) var(--ca-ease-out), scale var(--ca-dur-fast) var(--ca-ease-out);
}
/* .ca-cta__w is declared with .c-btn__w in components.css: one implementation. */
.ca-cta--primary   { background: var(--ca-accent); }
.ca-cta--secondary { background: var(--ca-white); }
.ca-cta--tertiary  { background: var(--ca-tint); }
/* Hover. Terminal has NONE on these buttons: measured with a real pointer, and
   :hover matched while nothing changed. So this is ours, and it is two things at
   once on purpose.

   1. The tier steps one notch, which carries the whole affordance on its own and
      so still works when motion is off or the pointer is coarse.
   2. The stacked words lift 2px with a 40ms stagger on the second, which uses
      the per-word structure the stack already needs, costs no extra markup, and
      animates transform only so nothing reflows.

   120ms sits in the interface-response band, not the 700ms entrance band, and
   the global reduced-motion rule flattens the transform while leaving the
   colour step intact. */
@media (hover: hover) {
  .ca-cta--primary:hover   { background: var(--ca-accent-600); }
  .ca-cta--secondary:hover { background: var(--ca-tint); }
  .ca-cta--tertiary:hover  { background: var(--ca-white); }
  .ca-cta:hover .ca-cta__w { transform: translateY(-2px); }
  .ca-cta:hover .ca-cta__w + .ca-cta__w { transition-delay: 40ms; }
}
/* Below 1024 the cluster gives way to the menu button, as the nav already does */
@media (max-width: 1024px) { .ca-cta-cluster { display: none; } }

.ca-menu-btn {
  display: none; width: 48px; height: 48px; padding: 0;
  align-items: center; justify-content: center;
  background: none; border: 1px solid rgba(255,255,255,.28);
  border-radius: var(--ca-r-control); color: var(--ca-white); cursor: pointer;
  transition: scale var(--ca-dur-fast) var(--ca-ease-out);
}
.ca-menu-btn svg { width: 22px; height: 22px; }
.ca-menu {
  position: fixed; inset: 0; z-index: 150; background: var(--ca-white);
  padding: var(--ca-space-5); display: grid; align-content: start; gap: var(--ca-space-5);
  overflow-y: auto;
}
.ca-menu[hidden] { display: none; }
/* Settles 16px down into place on open and lifts 16px away on close, the
   dialog's own movement (D-258). Movement only: the panel is never faded (D-64). */
@media (prefers-reduced-motion: no-preference) {
  @keyframes ca-menu-in { from { transform: translateY(calc(-1 * var(--ca-space-4))); } to { transform: none; } }
  .ca-menu:not([hidden]) { animation: ca-menu-in var(--ca-dur-base) var(--ca-ease-out); }
  .ca-menu.is-closing { transform: translateY(calc(-1 * var(--ca-space-4))); transition: transform var(--ca-dur-fast) var(--ca-ease-in); }
}
.ca-menu__top { display: flex; align-items: center; justify-content: space-between; }
/* The menu's logo links home, as the masthead's does: Home is the logo and is
   not in the menu list, so on a phone this was the only way home and it was a
   plain image (Jacqui, raised before and again 2026-10-23, D-260). A35 guards it. */
.ca-menu__home { display: block; line-height: 0; border-radius: var(--ca-r-control); transition: scale var(--ca-dur-fast) var(--ca-ease-out); }
.ca-menu__home:active { scale: .97; }
.ca-menu__home:focus-visible { outline: 2px solid var(--ca-teal); outline-offset: 4px; }
.ca-menu__list { list-style: none; margin: 0; padding: 0; display: grid; }
.ca-menu__link {
  display: block; padding: var(--ca-space-5) 0;
  border-bottom: 1px solid var(--ca-hairline);
  color: var(--ca-teal); text-decoration: none;
  font-family: var(--ca-font-display); font-size: var(--ca-size-h3);
  font-weight: var(--ca-weight-h3); letter-spacing: var(--ca-track-h3);
}
@media (max-width: 1024px) {
  .ca-nav, .ca-header__actions .c-btn { display: none; }
  .ca-menu-btn { display: inline-flex; }
}

/* ---- Hero: full-bleed video on the dark ground -------------------------
   No white frame, no glass panel. Both of those were Fedgroup's hero. This is
   a cinematic full-bleed band with a gradient scrim, which is what both
   references do, and the data layer sits over the footage.                  */
/* ---- Hero: a framed stage that folds inward on scroll -------------------
   Jacqui, 2026-09-08, referring to lightshiprv.com, then refined against a
   screenshot she sent of it mid-fold: the surround is a LIGHT SURFACE, not the
   dark teal; the reduction goes much further and faster than my first attempt;
   and it happens on desktop only. D-95.

   Measured on their site: the hero media is inset 8px from every viewport edge.
   Their scroll mechanism could not be observed in the browser pane, so the fold
   is built from Jacqui's description and her screenshot. */
.ca-hero {
  position: relative;
  /* The ground revealed as the frame folds. Was the teal, which read as a dark
     band; it is the soft surface, so the fold opens into the page rather than
     into a void, and flows into the white section below. */
  background: var(--ca-bg-tint);
  padding: var(--ca-space-2);
  overflow: clip;
}
.ca-hero__frame {
  position: relative; overflow: hidden;
  border-radius: var(--ca-r-media);
  /* Fills the viewport exactly at rest: frame plus the 8px of surround top and
     bottom. At min(88svh, 860px) the statement's first line peeked above the
     fold. Jacqui, 2026-09-08: "it shouldnt show above the foldline". The 860
     cap goes with it, so on a tall monitor the hero is tall, which is what a
     full-bleed hero does. D-106. */
  min-height: calc(100svh - 2 * var(--ca-space-2));
  max-width: 100%;
  margin-inline: auto;
  display: flex; align-items: center;
  background: var(--ca-teal);
}
/* The hard shadow under white type on a picture sits 2px down, 1px on a phone,
   one step closer than before. Jacqui, 2026-10-15: "slightly too offset" (D-220). */
.ca-hero__media { position: absolute; inset: 0; z-index: 0; }
.ca-hero__media video, .ca-hero__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%;
  /* Lifted from .62/.85 (D-93), then from .78/.92 to .9 and full colour:
     Jacqui, 2026-10-15, "way too strong on the home page hero video and washes
     out the colour too much" (D-216). The scrim this filter once worked with
     was removed in D-122, so it was only dulling the footage. Then saturation
     up to 1.2 and brightness eased to .92: "still looks a bit desaturated, can
     you ramp up the saturation?" (Jacqui, 2026-10-15, D-224). OFF since D-341
     (2026-10-29): Lance's Hero_5 is graded, and on it the filter lifted
     saturation 15% and darkened 13%, away from his master. No filter. */
}
/* .ca-hero__scrim is GONE. Jacqui, 2026-09-08: "Remove your scrim completely
   and animate the words in white with a hard small shadow beneath the text."
   The headline now carries its own protection in the letterforms. What that
   costs is recorded in D-122, measured, not guessed. */
.ca-hero__in {
  position: relative; z-index: 2; width: 100%;
  max-width: var(--ca-content-max); margin-inline: auto;
  padding: var(--ca-space-14) var(--ca-gutter);
  text-align: center;
}
.ca-hero__title {
  max-width: 20ch; margin-inline: auto;
  color: var(--ca-white);
  /* One hard shadow, directly beneath, no blur. It gives every glyph a dark
     edge on the side the eye reads it against without putting anything over
     the picture. 3px at display size, 2px below 768 where the type is 40px. */
  text-shadow: 0 2px 0 rgba(22, 48, 41, .92);
}
@media (max-width: 767px) { .ca-hero__title { text-shadow: 0 1px 0 rgba(22, 48, 41, .92); } }
/* The headline animates in instead of arriving with the frame. Jacqui,
   2026-09-08: "Lets rather animate the text in when it can be seen." One
   movement, on load, finishing in under a second, and it holds after that: a
   hero H1 that comes and goes with the footage is not a heading. */
@keyframes ca-hero-title-in {
  /* MOVEMENT ONLY, no opacity. A fade from 0 put the H1 at opacity 0 at load and
     A18 caught it: "1 text blocks hidden without JS, h1.ca-hero__title". The
     check is right and the design is better for it, because the first frame of
     the page should already carry the headline. It rises into place instead. */
  from { transform: translateY(var(--ca-space-6)) }
  to   { transform: none }
}
@media (prefers-reduced-motion: no-preference) {
  .ca-hero__title { animation: ca-hero-title-in var(--ca-dur-entrance) var(--ca-ease-out) both; }
}

/* The fold. DESKTOP ONLY, per Jacqui: on a phone the frame stays put, because
   there is no width to give away and a shrinking card on a 390px screen reads
   as a mistake rather than an effect.

   Faster and further than the first attempt: the range is half a viewport
   rather than a whole one, the surround opens 8px to 64px, and the frame gives
   up a third of its width and a quarter of its height, so it becomes a card
   sitting in the page rather than a bleed with a border. */
@supports (animation-timeline: scroll(root)) {
  @media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
    @keyframes ca-hero-fold {
      from { padding: var(--ca-space-2); }
      to   { padding: var(--ca-space-10); }
    }
    @keyframes ca-hero-fold-frame {
      from { border-radius: var(--ca-r-media); max-width: 100%;  min-height: calc(100svh - 2 * var(--ca-space-2)); }
      to   { border-radius: var(--ca-r-panel); max-width: 66%;   min-height: min(64svh, 640px); }
    }
    .ca-hero {
      animation: ca-hero-fold linear both;
      animation-timeline: scroll(root);
      /* scroll(root), not view(): with view() a hero that already fills the
         scrollport is part-way through its own exit range at scroll 0, and the
         frame opened to 13.7px before the visitor had scrolled at all. */
      animation-range: 0 50vh;
    }
    .ca-hero__frame {
      animation: ca-hero-fold-frame linear both;
      animation-timeline: scroll(root);
      animation-range: 0 50vh;
    }
  }
}

@media (max-width: 767px) {
  .ca-hero { padding: var(--ca-space-1); }
  .ca-hero__frame { min-height: calc(100svh - 2 * var(--ca-space-2)); }
  .ca-hero__in { padding: var(--ca-space-12) var(--ca-gutter) var(--ca-space-10); }
  .ca-hero__scrim { background: linear-gradient(180deg, rgba(22, 48, 41,.35) 0%, rgba(22, 48, 41,.72) 55%, rgba(22, 48, 41,.90) 100%); }
}

/* ---- Opening, the band the hero folds into --------------------------------
   The lead that came off the hero (D-95), then ONE photograph that opens from
   an inset panel to full width as it rises, echoing the hero fold. Replaces the
   opening statement and stacking cards (D-204): Tim found the cards covering the
   pinned paragraph confusing, and Jacqui chose this from two prototypes (D-203).
   The old CSS is in superseded/cardstack-2026-10-14/.

   Spacing is 64 above the paragraph, 64 below it, and 64 from the photograph to
   the stats title, which is why the band has no bottom padding: the stats band
   carries that 64 itself (.ca-content--after-photo). */
.ca-opener { background: var(--ca-bg); padding-block: var(--ca-space-10) 0; }
/* 88ch, not the 44ch the old statement used. At the statement size 44ch wrapped
   after three or four words a line and ran to six lines; Jacqui, 2026-10-12:
   "the paragraph wraps too quickly for the size of the text". */
.ca-opener__head {
  max-width: min(88ch, calc(100% - 2 * var(--ca-gutter)));
  margin: 0 auto var(--ca-space-10);
  text-align: center;
}
.ca-opener__lede {
  margin: 0; font-family: var(--ca-font-display); font-size: var(--ca-size-statement);
  font-weight: var(--ca-weight-h1); line-height: var(--ca-lh-tight);
}
/* Static state, for a phone, reduced motion, and browsers without scroll
   timelines: the inset panel at 66%. */
.ca-opener__frame { margin: 0 auto; width: 66%; border-radius: var(--ca-r-panel); overflow: hidden; }
.ca-opener__frame img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; }
/* The opening. The box is FULL WIDTH and a FIXED HEIGHT the whole time and only
   the clip moves, so the animation cannot change the page's layout. Animating
   width did: the photograph's height followed its width, the page length moved
   under the scroll position, and the view() timeline driving the animation moved
   with it (measured 2026-10-12: width read 950, 1341, then 950 again). It ends on
   the hero's own 8px surround and media radius. */
@supports (animation-timeline: view()) {
  @media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
    @keyframes ca-opener-open {
      from { clip-path: inset(0 17% round var(--ca-r-panel)); }
      to   { clip-path: inset(0 var(--ca-space-2) round var(--ca-r-media)); }
    }
    .ca-opener__frame {
      /* A true 2:1 at every width, capped by the viewport on short screens. The
         old min(80svh, 800px) let the strip get relatively shallower on wide
         screens, so the crop, and the mark, moved with the screen (D-214). */
      width: 100%; height: min(90svh, 50vw); border-radius: 0; overflow: visible;
      animation: ca-opener-open linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 40%;
    }
    /* The photograph is exported at its own 4:3 and the 2:1 strip shows two
       thirds of its height. The sky is the top quarter and the mark ends about
       79% down, so not all of both fit: 45% keeps the orange sky band and the
       treeline above the roof, with about 3% clear under the mark. Jacqui,
       2026-10-15: "move the factory down in the crop ... there is no sky" (D-214). */
    .ca-opener__frame img { height: 100%; aspect-ratio: auto; object-position: 50% 45%; }
  }
}
@media (max-width: 767px) {
  .ca-opener__frame { width: 100%; }
}
/* The stats band directly under the photograph: its title closes up to 64 at
   every width. Jacqui, 2026-10-14: "move the caption down to become a title
   above the stats and close the padding". */
.ca-content--after-photo { padding-top: var(--ca-space-9); }   /* 64 to 56 (D-251) */

/* ---- Film, Lance's process film under the stats (D-207) -----------------
   Click to play, never on its own: it is 2:25 with a music track. The frame is
   16:9 on the dark ground, the media radius like every photograph. The play
   button is the masthead glass recipe, the same one .ca-totop uses, at label
   size with the triangle in the accent. The markup carries native controls and
   the script swaps them for this button, so with scripts off the film plays. */
.ca-film {
  position: relative; margin: 0;
  aspect-ratio: 16 / 9;
  border-radius: var(--ca-r-media); overflow: hidden;
  background: var(--ca-teal);
}
.ca-film__video { display: block; width: 100%; height: 100%; object-fit: cover; }
.ca-film__play {
  /* Centred by translate, not inset 0 plus margin auto: that computes a 306px
     margin, off the spacing scale, and A10 reads computed margins. */
  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  transition: scale var(--ca-dur-fast) var(--ca-ease-out);
  display: inline-flex; align-items: center; gap: var(--ca-space-3);
  padding: var(--ca-space-4) var(--ca-space-6);
  border-radius: var(--ca-r-control);
  color: var(--ca-white);
  font-family: var(--ca-font-label); font-size: var(--ca-size-eyebrow);
  font-weight: var(--ca-weight-semibold); line-height: var(--ca-lh-flat);
  letter-spacing: var(--ca-track-eyebrow); text-transform: uppercase;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, .06) 40%, rgba(255, 255, 255, 0) 50%),
    rgba(22, 48, 41, .74);
  border: 1px solid rgba(255, 255, 255, .30);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    inset 0 -1px 0 rgba(22, 48, 41, .25),
    0 8px 24px rgba(22, 48, 41, .18);
  cursor: pointer;
}
@supports (backdrop-filter: blur(30px)) {
  .ca-film__play {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, .06) 40%, rgba(255, 255, 255, 0) 50%),
      rgba(22, 48, 41, .60);
    backdrop-filter: blur(20px) saturate(160%);
  }
}
.ca-film__play svg { display: block; color: var(--ca-accent); transition: transform var(--ca-dur-fast) var(--ca-ease-out); }
@media (hover: hover) { .ca-film__play:hover svg { transform: scale(1.12); } }
.ca-film__play:focus-visible { outline: 2px solid var(--ca-accent); outline-offset: 3px; }
.ca-film__time { color: var(--ca-tint); font-weight: var(--ca-weight-regular); }
/* Loading, between the press and the first moving frame (D-258): the label
   reads "Loading", the running time steps aside and the triangle breathes in
   scale. With motion off it simply reads "Loading". */
.ca-film__play.is-loading { cursor: progress; }
.ca-film__play.is-loading .ca-film__time { display: none; }
@media (prefers-reduced-motion: no-preference) {
  @keyframes ca-play-wait { from { transform: scale(1); } to { transform: scale(.72); } }
  .ca-film__play.is-loading svg { animation: ca-play-wait 600ms var(--ca-ease-out) infinite alternate; }
}
/* The film band is half the usual band height, 64 top and bottom. Jacqui,
   2026-10-14: "decrease the green ground so it has less padding" (D-209). */
.ca-content--film { padding-block: var(--ca-space-9); }   /* 64 to 56, still the tightest band (D-209, D-251) */
/* Francois's interview on our-story.html is this same component (D-254): the
   held frame and its marker rules went when the cut landed. */
@media (max-width: 767px) {
  .ca-film__play { padding: var(--ca-space-3) var(--ca-space-5); font-size: var(--ca-size-small); }
}

/* "Different commercial possibilities." keeps its last two words together
   (a non-breaking space in the markup, Tim's line-break thread, D-211). The
   Who it's for title is 32px on a phone and the phrase needs 344px there, so
   below 390 that one free-measure title steps down to 26px, the largest size
   at which the phrase fits a 320 screen (279px of 288). */
@media (max-width: 389px) { .ca-pagehead .ca-h-free { font-size: 26px; } }
/* The home heading holds the phrase with a span, not a non-breaking space,
   and only from 390 up: at 320 with the WCAG text-spacing override the joined
   phrase is wider than the screen and A9 caught the overflow. Below 390 it may
   wrap, which is the lesser fault. */
@media (min-width: 390px) { .ca-keep { white-space: nowrap; } }

/* ---- Interior page head ------------------------------------------------- */
.ca-pagehead { background: var(--ca-teal); 
  /* Clears the floating panel, which now overlays the top of every page. On
     the scale, not a calc: the panel's bottom edge sits at 24 + 76 = 100px, so
     160 leaves 60px of air. calc(76 + 64) resolved to 140px and A10 correctly
     called it off-scale. */
  padding-top: var(--ca-space-14);
}
/* A photograph full-bleed behind the green head, on the pages that have one
   (technology, farms; D-215). The green stays underneath as the ground while
   the image loads and wherever it does not cover. The text keeps its colours
   and takes the home hero's protection, one hard shadow and no scrim (D-122). */
.ca-pagehead--photo { position: relative; isolation: isolate; overflow: hidden; }
.ca-pagehead__media { position: absolute; inset: 0; z-index: -1; display: block; }
.ca-pagehead__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Technology's head: the frame is bright glass above a wall of lettuce, so the
   crop sits low and the eyebrow lands on the leaves rather than the glass
   (Jacqui, 2026-10-15, "nudge the crop"; D-217). */
.ca-pagehead__media--low img { object-position: 50% 78%; }
/* The green FEATHER, on EVERY photograph in a green head, not a wash over the
   whole image: Jacqui, 2026-10-15, "rather use a gradient feather that becomes
   0% opacity as it moves up" (D-221), then "treat all hero images with the same
   gradient effect" (D-222). Since D-272 it is set from the top: clear to
   140px, easing in to the eyebrow at 256px, full from the title to the foot,
   so the photograph above the type is untouched at every width. The home hero video is not a page head and keeps
   no overlay. */
.ca-pagehead__media::after {
  content: ""; position: absolute; inset: 0;
  /* D-272, Jacqui 2026-10-23: the old feather "is almost covering the whole hero on mobile", it must be "a gradual
     feather out on both desktop and mobile", and then, once it ended below the type, "it must go above the eyebrow
     as the eyebrow becomes difficult to read on technology hero". Measured: on every page at every width from 320
     to 1440 the eyebrow's top sits exactly 256px below the head's top (the head's top padding absorbs the masthead
     change), and only the foot moves. So the feather is set from the TOP in px: clear behind and just under the
     masthead to 140, easing in to 40% at the eyebrow's top and the full 45% from the title (296) to the foot. The
     top of every photograph is untouched; the eyebrow and title always sit on the feather. */
  background: linear-gradient(to bottom,
    rgba(22, 48, 41, 0) 0, rgba(22, 48, 41, 0) 140px, rgba(22, 48, 41, .12) 180px, rgba(22, 48, 41, .28) 220px,
    rgba(22, 48, 41, .40) 256px, rgba(22, 48, 41, .45) 296px, rgba(22, 48, 41, .45) 100%);
}
.ca-pagehead--photo h1,
.ca-pagehead--photo .ca-lead,
.ca-pagehead--photo .ca-eyebrow { text-shadow: 0 2px 0 rgba(22, 48, 41, .92); }
/* The lead goes white over a photograph. In the pale tint it read 3.0:1 median
   over technology's head at the 45% wash, under the 4.5 body text needs; white
   reads as the title does (D-215). Plain green heads keep the tint. */
.ca-pagehead--photo .ca-lead { color: var(--ca-white); }
@media (max-width: 767px) {
  .ca-pagehead--photo h1,
  .ca-pagehead--photo .ca-lead,
  .ca-pagehead--photo .ca-eyebrow { text-shadow: 0 1px 0 rgba(22, 48, 41, .92); }
}
.ca-pagehead__in {
  max-width: var(--ca-content-max); margin-inline: auto;
  padding: var(--ca-space-12) var(--ca-gutter) var(--ca-space-11);
}
/* Phones: the type sits lower in the head, 84 to 64 below it (Jacqui, 2026-10-23,
   "move the text down a bit on mobile", D-273). The top is untouched, so the
   eyebrow stays 256 below the head's top and the feather (D-272) still lands on it. */
@media (max-width: 767px) { .ca-pagehead__in { padding-bottom: var(--ca-space-10); } }
/* A MEASURE on the page title, so it breaks instead of running the width of the
   band. Jacqui, 2026-09-08: "make a rule that breaks the hero line so it wraps
   (see technology hero)."

   Measured before choosing the number. At 1440 and 1280 six of the seven page
   titles were setting as ONE line of 34 to 49 characters across a 1248px band:
   technology 42, who-its-for 47, why-can-agri 46, farms 49, partners 34,
   contact 39. `text-wrap: balance` was already on every h1 and could do nothing
   about it, because balance rebalances breaks that exist and will not introduce
   one.

   20ch, arrived at by measuring the true one-line width of all six titles at
   1440 rather than by trying numbers: partners 870, contact 1033, technology
   1127, why-can-agri 1203, who-its-for 1227, farms 1293. `ch` is the width of a
   zero and Valley Sans sets a wide one, so 26ch was 1077px and still held a 39
   character title on one line; 22ch at 929px broke five of the six and left
   partners at 870 running on. 20ch is about 845px, under the shortest of them,
   so every title breaks, and the longest at 1293 still lands on two lines
   rather than three. It is also the same measure the home hero already uses,
   so the page titles and the hero now share one number instead of two.
   Below 768 the column is already narrower than 26ch, so the cap does nothing
   and the natural wrap stands. The home hero keeps its own tighter 20ch: it is
   centred, it is one short sentence, and it is a different job. D-154. */
.ca-pagehead h1 { max-width: 20ch; }
/* Title and lead closer in scale on the page heads (D-227). */
.ca-pagehead h1 { font-size: var(--ca-size-pagehead-title); }
.ca-pagehead .ca-lead { font-size: var(--ca-size-pagehead-lead); font-weight: var(--ca-weight-regular); }   /* the page-head lead stays regular over the photographs (D-247) */
/* A wider measure than the section lead's 48ch, so a one-line page-head lead stays one line on desktop. Measured
   (D-323): the Farms lead needs 724px at 1280 and 789 at 1440; 52ch is 758 and 827. The two long leads, Partners and
   Contact, still take two lines of about 57 characters. */
.ca-pagehead .ca-lead { max-width: 52ch; }
/* The halved 4px was too tight on the green page heads (Jacqui, 2026-10-12),
   where a 60px title sits under a 14.5px eyebrow. Back to 8 here only; feature
   cards and dialogs keep their 4. D-202. */
.ca-pagehead .ca-eyebrow { margin-bottom: var(--ca-space-1); }   /* 8 to 4, D-243 */
/* And a gap under it. The lead had no top margin, because the rule that spaces
   a page head's children is `.ca-head > * + *` and the pagehead lays its own
   out directly, so `p + p` never matched across the h1 between them. It was
   invisible while the title was one line and obvious the moment it became two. */
.ca-pagehead h1 + .ca-lead { margin-top: var(--ca-space-3); }

/* ---- Partner strip: a white band above the footer ---------------------
   Fedgroup's reversed logo keeps a FedBlue bar, and FedBlue on the CAN-Agri
   ground is 1.15:1, so the strip cannot sit inside the teal footer without an
   all-white lock-up. Text credits until artwork and permission exist.       */
/* The official lock-up with the gable, light variant, because the footer is
   the teal ground. #bfd5d2 in the file, which is the tint. D-145. */
.ca-footer__mark img { display: block; width: auto; height: 96px; }
@media (max-width: 767px) { .ca-footer__mark img { height: 76px; } }

.ca-partners { background: var(--ca-white); border-top: 1px solid var(--ca-hairline); }
.ca-partners__in {
  max-width: var(--ca-content-max); margin-inline: auto;
  padding: var(--ca-space-9) var(--ca-gutter);   /* 64 to 56 (D-251) */
}
.ca-partners__row {
  display: grid; grid-template-columns: repeat(2, minmax(0, 320px));
  gap: var(--ca-gutter); margin-top: var(--ca-space-6);
}
.ca-partners__in > .ca-eyebrow + .ca-partners__row { margin-top: var(--ca-space-3); }   /* 32 to 16, D-202; 16 to 12, D-243 */
.ca-partner { display: grid; gap: var(--ca-space-2); }
/* Supplied artwork, placed as supplied. Fixed rule 5: never recoloured, never
   distorted, never cropped, no white fill behind them, never over a photograph.
   So they are <img> references rather than inline SVG, which also keeps
   Fedgroup's #111c4d and #e81f76 inside the asset instead of in our computed
   styles, and the width and height come from each file's own viewBox ratio:
   Durr 597 by 288 is 2.073, Fedgroup 396.6 by 73 is 5.433. Both sit at 36 high.
   Fedgroup's file was re-supplied on 2026-09-08 with its baked-in padding
   stripped, which changed the viewBox from 318.7 by 82.5 to 396.6 by 73: the
   artwork now fills its own box, so equal pixel height is equal visual height
   and the two marks match without a fudge factor. Its width attribute went
   from 139 to 196 to keep the new ratio. D-145, D-147. */
.ca-partner__logo { display: block; width: auto; height: 36px; }
@media (max-width: 480px) { .ca-partner__logo { height: 30px; } }
.ca-partner__name {
  font-family: var(--ca-font-display); font-size: var(--ca-size-h4);
  font-weight: var(--ca-weight-semibold); letter-spacing: var(--ca-track-h4);
  color: var(--ca-teal); text-decoration: none;
}
.ca-partner__role {
  font-family: var(--ca-font-label); font-size: var(--ca-size-caption);
  letter-spacing: .06em; color: var(--ca-muted);
}
/* The split line under the logos, and the rule above it, are removed (D-326). */

/* ---- Footer ------------------------------------------------------------- */
.ca-footer { background: var(--ca-teal); color: var(--ca-tint); }
.ca-footer__in {
  max-width: var(--ca-content-max); margin-inline: auto;
  padding: var(--ca-space-11) var(--ca-gutter) var(--ca-space-8);
}
.ca-footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--ca-space-8); }
.ca-footer__colhead {
  font-family: var(--ca-font-label); font-size: var(--ca-size-caption);
  letter-spacing: var(--ca-track-eyebrow); text-transform: uppercase;
  color: var(--ca-accent); margin: 0 0 var(--ca-space-3) 0;  /* halved from space-5 */
}
.ca-footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ca-space-3); }
.ca-footer__list a, .ca-footer a { color: var(--ca-tint); }
@media (hover: hover) { .ca-footer a:hover { color: var(--ca-white); } }
/* Was a labelled accent box while the lock-up was a placeholder. Now it holds
   the real mark, reversed: plain white, no border, no accent. The accent is
   rationed to one or two elements a screen (D-59) and it is not a lock-up
   colour in the CI. */
.ca-footer__mark { display: inline-block; line-height: 0; border-radius: var(--ca-r-control); transition: scale var(--ca-dur-fast) var(--ca-ease-out); }
/* The footer mark links home like the masthead and menu marks (D-260, Jacqui 2026-10-23). */
.ca-footer__mark:active { scale: .97; }
.ca-footer__mark:focus-visible { outline: 2px solid var(--ca-accent); outline-offset: 4px; }
.ca-footer__blurb { margin-top: var(--ca-space-5); max-width: 46ch; color: var(--ca-tint); }
.ca-footer__legal {
  margin-top: var(--ca-space-10); padding-top: var(--ca-space-5);
  border-top: 1px solid rgba(192,214,211,.25);
  display: flex; flex-wrap: wrap; gap: var(--ca-space-5); justify-content: space-between;
  font-family: var(--ca-font-label); font-size: var(--ca-size-caption); letter-spacing: .04em;
}
.ca-footer__legal ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--ca-space-4); }
@media (max-width: 767px) {
  .ca-footer__grid { grid-template-columns: 1fr; gap: var(--ca-space-8); }
  .ca-partners__row { grid-template-columns: 1fr; gap: var(--ca-space-6); }
}

/* ---- The audience switch ----------------------------------------------- */
/* 5fr to 7fr and CENTRED, deliberately not the Z's 4fr to 7fr top aligned.
   Jacqui, 2026-09-08: "keep the tabs, revert that, yours is cramped and doesn't
   work." The Z's proportions suit the rows on who-its-for and farms, where the
   text carries an eyebrow, a heading, a lead, a four-item list and a CTA and so
   runs as tall as the picture. A tab panel carries a heading and one paragraph:
   in a 419px column under a 733px image it left about 350px of empty space
   beside the picture, which is exactly the cramped reading. Short text wants
   the wider track and the vertical centre. D-144. */
/* Top aligned, like `.ca-row--wide` (D-139), not centred. In the technology
   tabs the text is a heading and one paragraph, about 160px, beside a 3:2 image
   of 448: centred, the heading started 192px below the tab row while the image
   started 48px below it, and the 144px of empty column above the heading read
   as dead space. Top aligned, heading and image start together, 48 below the
   tabs. On the home page's audience tabs the text is the tall element (475
   against 448), so this moves the image up by 14px and nothing else. D-169. */
.ca-audience { display: grid; grid-template-columns: 5fr 7fr; gap: var(--ca-gutter); align-items: start; }
@media (max-width: 1024px) { .ca-audience { grid-template-columns: 1fr; gap: var(--ca-space-8); } }

/* ---- The partnership band ---------------------------------------------- */
.ca-partnerband__in {
  max-width: var(--ca-content-max); margin-inline: auto;
  padding: var(--ca-space-10) var(--ca-gutter);   /* 84 to 64 (D-251) */
}
/* The button sits in the text stack as a .ca-cta-row, under its paragraph, as in the audience panels. It was a
   space-between flex row that pushed it to the far right on desktop, away from the copy it belongs to (D-338). */
.ca-partnerband__text { max-width: 60ch; }

/* ---- Legal placeholder pages and 404 ---------------------------------- */
.ca-placeholder {
  padding: var(--ca-space-5); background: var(--ca-soft);
  border-radius: var(--ca-r-media); border: 1px solid var(--ca-hairline);
  font-family: var(--ca-font-label); font-size: var(--ca-size-caption);
  letter-spacing: var(--ca-track-eyebrow); text-transform: uppercase;
  color: var(--ca-accent-800); max-width: 60ch;
  margin-bottom: var(--ca-space-6);   /* sat at 0 against the page's heading on all four legal pages; found by A34 (D-259) */
}

/* ---- Back to top (every page) -------------------------------------------
   Jacqui, 2026-10-09: "a glass back to top button on every page of the site,
   with an arrow in the accent colour". The masthead's own glass recipe at the
   menu button's 48px. Jacqui, same day: "too dark, make it a bit more glassy".
   So it is LIGHTER than the bar: tint .60 rather than .67, a sheen across the
   top half, a brighter rim and a softer, paler lift. The tint cannot go much
   further, because the arrow is the accent and the accent loses contrast fast
   as the glass thins. MEASURED at its worst, the glass composited over a white
   band: .67 gave 3.85:1, .60 gives 3.12:1, .55 would give 2.71:1. It is a
   graphic, so the bar is 3:1 (WCAG 1.4.11), and .60 is the lightest that
   clears it. The sheen fades out above the arrow's centre. The no-blur
   fallback is .74, 4.8:1.

   Its right edge sits on the masthead panel's right edge at every width: the
   panel is centred at min(content-max, 100% - 2 gutters), so the same
   arithmetic gives the offset. Fixed boxes resolve 100% against the viewport.

   It PARKS below the fold edge at the top of a page and slides up once the
   reader is a screen down. Transform only, never opacity (the house motion
   rule), and visibility follows so a parked button is out of the tab order.
   The parked state is added by the script, so with scripts off the button is
   simply always there and the #top anchor still works. */
.ca-totop {
  position: fixed; z-index: 90;
  right: max(var(--ca-gutter), calc((100% - var(--ca-content-max)) / 2));
  bottom: var(--ca-space-5);
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px;
  border-radius: var(--ca-r-control);
  color: var(--ca-accent);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, .06) 40%, rgba(255, 255, 255, 0) 50%),
    rgba(22, 48, 41, .74);
  border: 1px solid rgba(255, 255, 255, .30);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    inset 0 -1px 0 rgba(22, 48, 41, .25),
    0 8px 24px rgba(22, 48, 41, .18);
  transition: transform var(--ca-dur-slow) var(--ca-ease-out), visibility 0s linear 0s, scale var(--ca-dur-fast) var(--ca-ease-out);
}
@supports (backdrop-filter: blur(30px)) {
  .ca-totop {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, .06) 40%, rgba(255, 255, 255, 0) 50%),
      rgba(22, 48, 41, .60);
    backdrop-filter: blur(20px) saturate(160%);
  }
}
/* It lives inside the footer (the contentinfo landmark, or axe flags it as
   content outside a region), so it must out-rank the footer's link colours. */
.ca-footer a.ca-totop, .ca-footer a.ca-totop:hover { color: var(--ca-accent); text-decoration: none; }
.ca-totop svg { display: block; transition: transform var(--ca-dur-fast) var(--ca-ease-out); }
@media (hover: hover) { .ca-totop:hover svg { transform: translateY(-2px); } }
.ca-totop:focus-visible { outline: 2px solid var(--ca-accent); outline-offset: 3px; }
/* Parked: pushed down past the viewport edge by its own height plus its gap. */
.ca-totop.is-parked {
  transform: translateY(calc(100% + var(--ca-space-5) + 2px));
  visibility: hidden;
  transition: transform var(--ca-dur-slow) var(--ca-ease-in), visibility 0s linear var(--ca-dur-slow);
}
@media (max-width: 767px) {
  .ca-totop { bottom: var(--ca-space-4); }
  .ca-totop.is-parked { transform: translateY(calc(100% + var(--ca-space-4) + 2px)); }
}
@media (prefers-reduced-motion: reduce) {
  .ca-totop, .ca-totop.is-parked, .ca-totop svg { transition: none; }
}


/* Text beside an image: the text block is inset 24px all round (top, right, bottom, left), and the column gap is reduced by the same 24px so the visible distance from image to text stays equal to the gutter (96px on wide screens). Every text-and-image row and the home audience tabs, only where they sit side by side (1025px and up); below that they stack full width. Jacqui, 2026-11-09. */
@media (min-width: 1025px) {
  :is(.ca-row--wide, .ca-audience) > .ca-stack { padding: var(--ca-space-5); }
  :is(.ca-row--wide, .ca-audience) { column-gap: calc(var(--ca-gutter) - var(--ca-space-5)); }
}

/* Form labels (Contact form): one size below the caption token, 12px to 11px. Jacqui, 2026-11-10. */
.c-field .c-field__label { font-size: calc(var(--ca-size-caption) - 1px); }

/* Legal pages (privacy, cookies, terms, PAIA all use section#legal): reading rhythm for long documents. 16px between blocks, section headings at the H3 size (25px) with 48px above, sub-headings at the H4 size (19px) with 32px above, 12px from any heading to its text. Jacqui, 2026-11-10. */
#legal .ca-content > * + * { margin-top: var(--ca-space-4); }
#legal .ca-content > h2 { font-size: var(--ca-size-h3); margin-top: var(--ca-space-8); }
#legal .ca-content > h3 { font-size: var(--ca-size-h4); margin-top: var(--ca-space-6); }
#legal .ca-content > :is(h2, h3) + * { margin-top: var(--ca-space-3); }

/* Home opener image on phones: keep the page margin either side, like every other stacked image (it ran edge to edge with rounded corners). Tablet and desktop keep the scroll-grow to full width. Jacqui, 2026-11-10. */
@media (max-width: 767px) {
  .ca-opener__frame { width: calc(100% - 2 * var(--ca-gutter)); }
}
