/* =========================================================
   Section redesign — INDUSTRIES. See REDESIGN-BRIEF.md.

   Loads after pages.css so it can override the .tile/.g3/.vlist rules it
   replaces. Scoped to this page only; nothing here ships to the other six.

   Archetypes, in page order:

     hero      0 · footage band + sector index
     sectors   4 · pinned horizontal track   <- the page's one moment
     support   5 · full-bleed split with photography
     cases     2 · editorial bento (deliberately unequal cells)

   No uniform grid and no .tile survives on this page. Colour is tokens
   only; molten and ember are labels, indices and rules, never a button.
   ========================================================= */

/* =========================================================
   0 · HERO — the feed

   .phero and .phero__* live in shared pages.css, which is not
   editable from here; everything below overrides it under
   `.phero--feed` and so lands on this page only.

   Two storeys. Upstairs is a full-width band of footage with the
   title standing in it. Downstairs is navy: the copy on the left,
   an index of all seven sectors on the right. The band is the only
   place on the site outside the homepage where text sits on moving
   pictures, so the scrim below is not decoration — it is what makes
   the eyebrow and the h1 legible against a bright sky, and it is
   measured at glyph pixels by _qc/feedcontrast.js.
   ========================================================= */

.phero--feed {
  /* the band starts at the very top of the page, under the fixed
     header, so the shared hero's top padding has to go */
  padding-top: 0;
  padding-bottom: clamp(2.4rem, 6vh, 4rem);
}
/* The radial wash belongs to the text-only hero this replaces; below
   the band it would fight the footage above it. */
.phero--feed .phero__bg { display: none; }

.ifeed {
  position: relative;
  display: flex; align-items: flex-end;
  min-height: clamp(300px, 46vh, 460px);
  overflow: hidden;
  background: var(--navy-900);
  /* contains the grade's mix-blend-mode: without this it would
     multiply against the page behind the band, not against the
     picture inside it */
  isolation: isolate;
}

.ifeed__still, .ifeed__vid {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 58% 42%;
  /* Close to the .ph--live grade in main.css. This surface carries
     overlaid copy, but the legibility work is done by the three shaped
     ramps below rather than by flattening the whole picture — that is
     what keeps the aircraft readable at all. */
  filter: saturate(.94) brightness(.97) contrast(1.04);
}
/* The still is painted from the first frame and the clip fades in on
   top of it once it can actually play. Same frame, so the handover is
   invisible; and if the gate holds, or autoplay is refused, what stays
   on screen is a real composition rather than a degraded one. */
.ifeed__vid { z-index: 1; opacity: 0; transition: opacity var(--d-m) var(--e-quad); }
.ifeed__vid.is-playing { opacity: 1; }

/* Navy tint: the source is a pale sky, and a pale sky is both off-brand
   on a navy-dominant site and the worst possible ground for molten text. */
.ifeed__grade {
  position: absolute; inset: 0; z-index: 2; display: block;
  background: var(--navy-800); mix-blend-mode: multiply; opacity: .28;
}
/* Three ramps, each doing one job:
     down from the top — the header is fixed, transparent until it
       sticks, and white nav links over a lit sky is a contrast failure
       the visitor meets before anything else on the page;
     up from the bottom — the eyebrow and the h1 stand here;
     in from the left  — the copy column, and it keeps the aircraft
       (right of frame) in clear air.
   The middle of the band is left almost untouched, which is where the
   picture actually lives. */
.ifeed__scrim {
  position: absolute; inset: 0; z-index: 3; display: block;
  background:
    linear-gradient(to bottom,
      rgba(6,21,41,.92) 0%, rgba(6,21,41,.60) 13%,
      rgba(6,21,41,.12) 30%, rgba(6,21,41,0) 44%),
    linear-gradient(to top,
      rgba(6,21,41,.97) 0%, rgba(6,21,41,.94) 26%,
      rgba(6,21,41,.78) 46%, rgba(6,21,41,.40) 66%,
      rgba(6,21,41,.10) 84%, rgba(6,21,41,0) 100%),
    linear-gradient(to right,
      rgba(6,21,41,.76) 0%, rgba(6,21,41,.40) 42%, rgba(6,21,41,0) 76%);
}

.ifeed__cap {
  position: relative; z-index: 4;
  padding-top: calc(var(--nav-h) + clamp(2.2rem, 7vh, 4rem));
  padding-bottom: clamp(1.2rem, 3vh, 2rem);
}
.phero--feed h1 { max-width: 13ch; }

/* --- downstairs: copy beside the index --- */

.ifeed__foot {
  padding-top: clamp(1.6rem, 4vh, 2.6rem);
  display: grid; gap: clamp(1.6rem, 4vw, 3.4rem);
  grid-template-columns: minmax(0, 1.18fr) minmax(0, .82fr);
  align-items: start;
}
.phero--feed .phero__sub { margin-top: 0; }

.ifeed__index { position: relative; padding-left: clamp(1rem, 2vw, 1.8rem); }
.ifeed__index::before {
  content: ''; position: absolute; left: 0; top: .25rem; bottom: .25rem;
  width: 1px; background: var(--rule-d);
}
.ifeed__idxhd {
  margin: 0 0 .5rem;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--molten);
}
.ifeed__index ul { list-style: none; margin: 0; padding: 0; }
.ifeed__index li {
  display: flex; align-items: baseline; gap: .6rem;
  border-bottom: 1px solid var(--rule-d);
}
.ifeed__index li:last-child { border-bottom: 0; }
.ifeed__index a {
  flex: 1 1 auto; display: block; padding: .42rem 0;
  color: var(--steel); text-decoration: none;
  font-size: var(--fs-small); letter-spacing: .01em;
  transition: color var(--d-xs) var(--e-out), transform var(--d-xs) var(--e-out);
}
.ifeed__index a:hover, .ifeed__index a:focus-visible {
  color: var(--white); transform: translateX(4px);
}
/* The one sector the footage is actually showing, said out loud so a
   single clip cannot be mistaken for the whole list. */
.ifeed__index .is-live a { color: var(--chrome); }
.ifeed__index .is-live span {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .1em; text-transform: uppercase; color: var(--ember);
  white-space: nowrap;
}
.ifeed__index .is-live span::before {
  content: ''; display: inline-block; vertical-align: middle;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--molten); margin-right: .45rem;
  box-shadow: 0 0 0 0 var(--glow);
}
.ifeed--live .is-live span::before { animation: ifeedpulse 2.6s var(--e-quad) infinite; }
@keyframes ifeedpulse {
  0%, 62%, 100% { box-shadow: 0 0 0 0 rgba(255,145,68,.55); }
  30%           { box-shadow: 0 0 0 6px rgba(255,145,68,0); }
}

@media (max-width: 899px) {
  .ifeed { min-height: clamp(240px, 40vh, 340px); }
  .ifeed__foot { grid-template-columns: minmax(0, 1fr); }
  .ifeed__index { padding-left: 0; padding-top: clamp(1rem, 3vh, 1.6rem); }
  .ifeed__index::before { left: 0; right: 0; top: 0; bottom: auto; width: auto; height: 1px; }
}

@media (prefers-reduced-motion: reduce) {
  /* The clip is never fetched in this mode (js/sec-industries.js holds
     the gate), so the still IS the hero. Nothing else here moves. */
  .ifeed__vid { display: none; }
  .ifeed--live .is-live span::before { animation: none; }
}

/* ---------------------------------------------------------
   1 · SECTORS — the tour.

   TWO layouts live in this block. The first is the DEFAULT: a vertical
   hairline ledger that needs no JavaScript, no pin and no motion, and
   is what a phone and a reduced-motion visitor get. `.stour--live`,
   added by js/sec-industries.js only when a pin is appropriate, turns
   the same markup on its side.
   --------------------------------------------------------- */

/* --- default: the vertical ledger --- */

.stour__hint { display: none; }

.stour__viewport { position: relative; }

.stour__track {
  list-style: none;
  margin: clamp(.6rem, 2vh, 1.4rem) auto 0;
  padding: 0 var(--gutter);
  max-width: var(--maxw);
  display: grid;
}

.stour__panel {
  position: relative;
  padding: clamp(1.6rem, 4.5vh, 2.8rem) 0;
  border-top: 1px solid var(--rule-d);
}
.stour__panel:last-child { border-bottom: 1px solid var(--rule-d); }

/* --- the sector photograph ---------------------------------------
   Added 2026-08-08, when the seven matched sector shots landed. The
   tour was typographic only because four of seven had a picture and
   two of those were defective; a track that alternates photo panels
   with blank ones reads as a bug, not as a rhythm.

   In the LEDGER it is a band above the words, so nothing sits on the
   picture and the phone gets the photographs at full strength. In the
   TRACK it moves behind the words and the scrim arrives with it —
   see the .stour--live block below. One markup, two jobs. */
.stour__shot {
  position: relative;
  height: clamp(150px, 40vw, 250px);
  margin: 0 0 clamp(1rem, 3vh, 1.5rem);
  overflow: hidden; border-radius: var(--rad);
  background: var(--navy-800);
  isolation: isolate;
}
.stour__shot img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(.94) brightness(.9) contrast(1.05);
}
.stour__grade {
  position: absolute; inset: 0; display: block;
  background: linear-gradient(to top, rgba(6,21,41,.55) 0%, rgba(6,21,41,.12) 46%, rgba(6,21,41,0) 100%);
}

.stour__ghost {
  /* Anchored to the FOOT of the row since the photograph took the top
     of it: the shot is later in the source and paints over anything
     positioned behind it, so a numeral hung from the top now hides
     under the picture instead of standing in the empty right column. */
  position: absolute; right: 0; bottom: clamp(1rem, 4vh, 2.4rem); top: auto;
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(3.4rem, 2rem + 6vw, 7rem);
  line-height: .78; letter-spacing: -.05em;
  color: var(--chrome); opacity: .07;
  pointer-events: none; user-select: none;
}

.stour__inner { position: relative; z-index: 1; max-width: 46ch; }

.stour__no {
  display: flex; align-items: center; gap: .75rem;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--molten); margin: 0 0 .85rem;
}
.stour__no::before { content: ''; width: clamp(24px, 3.4vw, 40px); height: 1px; background: currentColor; }

.stour__name {
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(1.45rem, 1.1rem + 1.35vw, 2.4rem);
  line-height: 1.06; letter-spacing: -.022em;
  color: var(--white); margin: 0 0 clamp(.6rem, 1.5vh, .95rem);
}

.stour__copy { color: var(--steel); max-width: 40ch; margin: 0; }

/* The old .vlist rings became ruled lines with a molten tick — the same
   information, in a shape the page does not use anywhere else. */
.stour__specs {
  list-style: none; margin: clamp(1rem, 2.6vh, 1.6rem) 0 0; padding: 0;
  border-top: 1px solid var(--rule-d);
}
.stour__specs li {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: .85rem; align-items: baseline;
  padding: .5rem 0; border-bottom: 1px solid var(--rule-d);
  font-size: var(--fs-small); color: var(--steel); line-height: 1.5;
}
.stour__specs li::before {
  content: ''; width: 12px; height: 1px; background: var(--molten);
  transform: translateY(-.32em);
}

.stour__inner .arrowlink { margin-top: clamp(1rem, 2.6vh, 1.5rem); }

.stour__rail { display: none; }

/* --- live: the pinned horizontal track --- */

.stour--live {
  --edge: max(var(--gutter), calc((100vw - var(--maxw)) / 2 + var(--gutter)));
}
.stour--live .stour__hint { display: block; }

.stour--live .stour__viewport {
  height: 100vh;
  overflow: hidden;
  margin-top: clamp(1rem, 3vh, 2rem);
}

.stour--live .stour__track {
  display: flex; align-items: center;
  max-width: none; height: 100%;
  margin: 0;
  padding: 0 var(--edge);
  gap: clamp(1.6rem, 3.4vw, 3.6rem);
  will-change: transform;
}

/* PANELS ARE LANDSCAPE, 2026-08-08. They were 500 wide by 640 tall —
   a PORTRAIT box holding a 16:9 LANDSCAPE photograph. `object-fit:
   cover` on a 0.78 box from a 1.79 source scales to fill the height and
   throws away well over half the width, so all seven sectors showed a
   narrow vertical core: sky above a windscreen, bare trees beside a
   train. Then the text scrim covered the bottom half of that. Daniel,
   correctly: "I can't even see what is the photo in it."

   Fixed at the root instead of by tuning the scrim. The panel now has
   the photograph's own proportion, the picture is a band rather than a
   backdrop, and the words sit BELOW it on solid navy — so no scrim has
   to sit on a photograph at all, and nothing competes for the frame. */
.stour--live .stour__panel {
  flex: 0 0 auto;
  width: clamp(430px, 54vw, 760px);
  /* One explicit height so seven photographs read as a single filmstrip.
     Auto height would leave each panel as tall as its own paragraph and
     the pictures would step up and down as the track travels. */
  height: min(76vh, 640px);
  display: flex; flex-direction: column; justify-content: flex-start;
  --stour-pad: clamp(1.4rem, 2.4vw, 2.1rem);
  padding: 0;
  border: 1px solid var(--rule-d); border-radius: var(--rad);
  overflow: hidden; isolation: isolate;
  /* The playhead. Everything off the reading line sits back a little,
     so the strip has a subject instead of seven equal cards. --on is
     written per frame by js/sec-industries.js: 0 dormant, 1 active. */
  --on: 0;
  transition: border-color var(--d-m) var(--e-out);
  border-color: color-mix(in srgb, var(--molten) calc(var(--on) * 38%), var(--rule-d));
}
.stour--live .stour__panel:last-child { border-bottom: 1px solid var(--rule-d); }

/* The photograph is now a band across the top of the panel and keeps
   its full width. A 760x372 window onto a 1920x1072 master crops only
   top and bottom — the subject, which in all seven shots runs across
   the frame, survives intact. */
.stour--live .stour__shot {
  position: relative; inset: auto; z-index: 0;
  flex: 0 0 auto;
  height: 50%; margin: 0; border-radius: 0;
  border-bottom: 1px solid var(--rule-d);
}

/* The image is wider than its window and slides against the travel, so
   the sides the crop would have cost are handed back over the panel's
   trip across the stage. This is the whole reason a 16:9 photograph can
   live in a horizontal filmstrip: the extra width becomes the motion
   rather than waste. --shift is written per frame, in px. */
.stour--live .stour__shot img {
  /* max-width:none is load-bearing, not tidying. assets/base.css:21 carries
     the usual `img, svg, canvas, video { max-width: 100% }` reset, which
     silently clamped this 116% back to 758px — the box measured exactly its
     window, so the parallax slid the picture off its own frame and opened a
     118px navy gap down one side. Any deliberately oversized image inside a
     window on this site has to opt out of that reset. */
  width: 116%; max-width: none; left: -8%; right: auto;
  transform: translate3d(var(--shift, 0px), 0, 0);
  filter: saturate(calc(.82 + var(--on) * .18))
          brightness(calc(.84 + var(--on) * .14))
          contrast(1.05);
}

/* Atmosphere only. It settles the picture into the panel and gives the
   ghost numeral something to sit on — it no longer has to carry any
   text legibility, because no text is on the photograph any more. */
.stour--live .stour__grade {
  background:
    linear-gradient(to top, rgba(6,21,41,.52) 0%, rgba(6,21,41,.10) 46%, rgba(6,21,41,0) 78%),
    linear-gradient(to right, rgba(6,21,41,.34), rgba(6,21,41,0) 52%);
}

/* No scrim behind the copy. It stands on the panel's own navy. */
.stour--live .stour__inner::before { content: none; }

.stour--live .stour__ghost {
  right: auto; bottom: auto; left: .04em; top: -.06em;
  font-size: clamp(4.6rem, 8vw, 7.6rem);
  opacity: calc(.10 + var(--on) * .10);
  z-index: 1;
}

.stour--live .stour__inner {
  max-width: none; position: relative; z-index: 2;
  flex: 1 1 auto; min-height: 0;
  padding: var(--stour-pad);
}

/* The paragraph stands down in the track — deliberately, after measuring.
   Half the panel is now photograph, which leaves ~250px for the words. The
   index, name, three ruled capability lines and View Solutions need ~238 of
   it; the paragraph needs another ~84 and something has to give. Between a
   generic sentence and three scannable capabilities, the capabilities win on
   a strip you travel past — and View Solutions must never be the thing that
   falls off the bottom edge, because it is the only way out of the panel.

   Nothing is lost: the LEDGER below 900px, under reduced motion and without
   JS carries the full paragraph, and that is the canonical layout. The track
   is the enhancement. Do not "fix" this by shrinking the photo band — that
   is the defect this whole redesign exists to correct. */
.stour--live .stour__copy { display: none; }
.stour--live .stour__specs { margin-top: clamp(.9rem, 2vh, 1.3rem); }

/* Wayfinding, pinned to the foot of the stage. */
.stour--live .stour__rail {
  display: block;
  position: absolute; left: 0; right: 0; bottom: clamp(1.4rem, 5vh, 3rem);
  z-index: 3;
}
.stour__railin {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: center; gap: clamp(1rem, 3vw, 2.2rem);
}
.stour__now {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--ember); margin: 0; white-space: nowrap;
}
.stour__bars { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; }
.stour__bars li { position: relative; height: 2px; background: var(--rule-d2); overflow: hidden; }
.stour__bars li::after {
  content: ''; position: absolute; inset: 0; background: var(--molten);
  transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
}
.stour__count {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .12em; color: var(--steel-dim); margin: 0; white-space: nowrap;
}
.stour__count b { color: var(--chrome); font-weight: 500; }

/* ---------------------------------------------------------
   2 · SUPPORT — full-bleed split.
   The photograph runs off the left edge and holds while the numbered
   ledger scrolls past it.
   --------------------------------------------------------- */

.isup__grid {
  --edge: max(var(--gutter), calc((100vw - var(--maxw)) / 2 + var(--gutter)));
  display: grid;
  grid-template-columns: 42fr 58fr;
  column-gap: clamp(1.6rem, 4vw, 4rem);
  align-items: stretch;
}
.isup__fig { position: relative; }
/* The frame sticks and clips; the photo inside is what drifts. Keeping the
   two jobs on separate elements is what stops the drift scale from pushing
   the document sideways at narrow widths. */
.isup__frame {
  position: sticky;
  top: calc(var(--nav-h) + clamp(1rem, 4vh, 2.4rem));
  height: clamp(300px, 64vh, 620px);
  overflow: hidden;
  border-radius: 0 var(--rad) var(--rad) 0;
}
.isup__frame .ph { position: absolute; inset: 0; }
.isup__body { padding-right: var(--edge); }

.isup__list {
  list-style: none; margin: clamp(1.6rem, 4vh, 2.4rem) 0 0; padding: 0;
  border-top: 1px solid var(--rule-l2);
}
.isup__item {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(.9rem, 2vw, 1.5rem);
  padding: clamp(1rem, 2.6vh, 1.55rem) 0;
  border-bottom: 1px solid var(--rule-l2);
}
.isup__no {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .16em; color: var(--molten-ink); padding-top: .4rem;
}
.isup__item h3 {
  font-family: var(--f-display); font-weight: 600; font-size: var(--fs-h3);
  letter-spacing: -.015em; color: var(--ink); margin: 0 0 .3rem;
}
.isup__item p { font-size: var(--fs-small); color: var(--slate); margin: 0; max-width: 52ch; }

@media (max-width: 900px) {
  .isup__grid { grid-template-columns: 1fr; row-gap: clamp(1.6rem, 4vh, 2.4rem); }
  /* `relative`, not `static`. The photo inside is absolutely positioned,
     so a static frame is not its containing block and overflow:hidden
     there does not clip it — the drift scale then pushed 13px of document
     overflow at 375px. Caught by _qc/sec-prodind.js. */
  .isup__frame {
    /* `top: auto` is load-bearing. The desktop rule sets a sticky offset of
       ~108px; switching to `relative` without clearing it leaves that offset
       in force, and on a relative element `top` shifts what is PAINTED while
       the layout box stays put. The photograph slid 108px down out of its own
       row and landed on the heading below it, which is what the client saw
       as an unreadable title over the picture. Client feedback 2026-08-31. */
    position: relative; top: auto; height: auto; aspect-ratio: 16 / 9;
    border-radius: 0;
  }
  .isup__body { padding: 0 var(--gutter); }
}

/* ---------------------------------------------------------
   3 · CASES — editorial bento.
   A plate divided by hairlines rather than four floating boxes: the
   lead case gets roughly three times the area of each of the others.
   --------------------------------------------------------- */

/* Lead over two rows, with the fourth cell full width beneath.

   This WAS "lead b / lead c / lead d" — one tall lead beside three stacked —
   and the note here said a full-width d cell "looked right on paper and left
   the d cell two thirds empty". True when every cell was type on navy. It
   stopped being true on 2026-08-09, when the photographs went in: a 4.3:1
   full-width cell is a good shape for a 16:9 picture (it crops top and bottom
   and keeps all the width), and the thing that used to leave it empty is now
   what fills it.

   The change also fixes the lead. At three rows tall its box was 758 x 728,
   nearly square, and its 16:9 band left ~600px of dead navy between the
   picture and the caption at the foot. Two rows puts the caption just under
   the band. */
.icase {
  display: grid;
  grid-template-columns: 1.32fr 1fr;
  grid-template-areas:
    "lead b"
    "lead c"
    "d    d";
  border-top: 1px solid var(--rule-d);
  border-left: 1px solid var(--rule-d);
}
.icase__cell {
  position: relative;
  --icase-pad: clamp(1.25rem, 2.6vw, 2.2rem);
  padding: var(--icase-pad);
  border-right: 1px solid var(--rule-d);
  border-bottom: 1px solid var(--rule-d);
  display: flex; flex-direction: column;
  /* Load-bearing for the motion in js/sec-industries.js cases(): the entrance
     scales each photograph from 1.06 and a scrub drifts it, both of which
     push the layer past the cell's edges. Without this the picture bleeds
     over the hairline into its neighbour. */
  overflow: hidden;
}
/* Every cell sets its copy at the FOOT. The lead is three rows tall and its
   air above used to be a deliberate poster margin; from 2026-08-08 that air
   is the photograph, and one consistent copy position means one bottom-up
   scrim serves all four rather than two opposing gradients. */
.icase__cell--lead { grid-area: lead; justify-content: flex-end; }
.icase__cell--b { grid-area: b; justify-content: flex-end; }
.icase__cell--c { grid-area: c; justify-content: flex-end; }
.icase__cell--d { grid-area: d; justify-content: flex-end; }

/* Minimum heights so a cell is a picture with a caption rather than a caption
   with a smear behind it. Raised from 230-300 on 2026-08-09 once the real
   photographs went in: at the old height the copy filled the cell and the
   scrim had to cover almost all of it, which muted the picture to the point
   of being pointless. The extra ~90px is clear photograph above the words.
   The lead spans all three rows and needs no minimum of its own. */
.icase__cell--b, .icase__cell--c, .icase__cell--d { min-height: clamp(310px, 36vh, 380px); }

/* THE PHOTOGRAPH. A .ph layer, not an <img>: assets/photos.js probes the
   file and only adds .ph--live if it really decoded, so until Daniel
   generates these four the cells fall back to the aluminium gradient and
   billet texture and the section still reads as finished. Wiring the slot
   before the file exists is the whole point of that system. */
.icase__ph {
  position: absolute; inset: 0; z-index: 0;
  border-radius: 0;
}

/* THE LEAD CELL IS A BAND, NOT A BACKDROP (fixed 2026-08-09, once the real
   photographs went in and the fault was visible).

   The lead spans all three rows, so its box measures 758 x 728 — very nearly
   SQUARE — and `background-size: cover` on a 16:9 photograph then matched the
   height and threw away 42% of the width. The battery tray lost both ends and
   read as an anonymous grey slab. Exactly the same defect as the sector tour,
   in a different section, and it is invisible until a real picture is in the
   slot: the placeholder gradient covers any box shape happily.

   `aspect-ratio: 16/9` on a top-anchored band makes the window match the
   photograph instead of the cell, so nothing is cropped horizontally. It is
   set in ratio rather than as a % of cell height on purpose — the cell's
   height is three stacked rows and moves whenever those change, and a
   percentage would silently re-break this. */
/* IN FLOW, not absolute. Absolutely positioned, the band was out of the flex
   flow, so the bottom-anchored caption knew nothing about it and the pills
   landed on the picture's lower edge — measured 2.69:1 against a bright part
   of the tray, where 4.5 is required. `sec-prodind.js` called that ALL PASS
   throughout, because it compares CSS colour pairs and reads the cell's navy
   rather than the photograph; `caseglyph.js` samples painted pixels and
   caught it immediately.

   As a flex item the caption simply follows the band, so no text sits on this
   photograph at all and it needs no scrim. Negative margins take it back out
   to the cell's edges. */
.icase__cell--lead { justify-content: flex-start; }
.icase__cell--lead .icase__ph {
  position: relative; inset: auto;
  flex: 0 0 auto;
  aspect-ratio: 16 / 9;
  margin: calc(-1 * var(--icase-pad)) calc(-1 * var(--icase-pad))
          clamp(1.1rem, 2.4vh, 1.6rem);
  border-bottom: 1px solid var(--rule-d);
}
.icase__cell--lead .icase__ph.ph--live::before { content: none; }

/* The three supporting cells stay full-bleed backdrops — their boxes are
   2.4:1, WIDER than the photograph, so cover crops top and bottom and the
   full width survives. Copy is bottom-anchored, so the scrim is too, and it
   now clears the picture entirely in the upper third. */
.icase__ph.ph--live::before {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to top,
    rgba(6,21,41,.95) 0%, rgba(6,21,41,.90) 42%,
    rgba(6,21,41,.55) 68%, rgba(6,21,41,.10) 100%);
}
.icase__ph.ph--live {
  filter: saturate(.92) brightness(.9) contrast(1.04);
  transition: filter var(--d-m) var(--e-out);
}
/* Hover warms the photograph. It has to be `filter` and not a transform:
   cases() scrubs a transform on this element for the whole time the plate is
   on screen, so a CSS `:hover { transform }` would be overwritten and
   silently do nothing — the same trap the homepage photo hover hit. And the
   hover state restates the WHOLE filter, because filter replaces rather than
   composes. */
.icase__cell:hover .icase__ph.ph--live,
.icase__cell:focus-within .icase__ph.ph--live {
  filter: saturate(1.02) brightness(1.02) contrast(1.04);
}

/* Everything that is not the picture sits above it. */
.icase__tags, .icase__cell h3,
.icase__cell p:not(.icase__tags),
.icase__cell .arrowlink { position: relative; z-index: 2; }

.icase__tags { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0; }
/* The pills carry their own ground on the three photo-backed cells. At 10.5px
   they need 4.5:1 and they sit high in the cell, where the scrim has already
   thinned to let the picture through — over the bright aircraft frames they
   measured 3.89. The alternative was a heavier scrim, which would have muted
   all three photographs to protect two words. A chip is local, and it makes
   the tags read as labels rather than as outlined text floating on a
   photograph. The lead cell has no photo behind its copy and needs none. */
.icase__tags .pill { color: var(--ember); }
.icase__cell:not(.icase__cell--lead) .icase__tags .pill {
  background: rgba(6,21,41,.78);
  backdrop-filter: blur(2px);
}

.icase__cell h3 {
  font-family: var(--f-display); font-weight: 600; font-size: var(--fs-h3);
  line-height: 1.16; letter-spacing: -.015em; color: var(--white);
  margin: clamp(.8rem, 2vh, 1.1rem) 0 .5rem;
}
.icase__cell--lead h3 {
  font-size: clamp(1.3rem, 1.05rem + .95vw, 1.95rem);
  line-height: 1.08; max-width: 14ch;
}
.icase__cell p:not(.icase__tags) { font-size: var(--fs-small); color: var(--steel); margin: 0; max-width: 44ch; }
.icase__cell--lead p:not(.icase__tags) { font-size: var(--fs-body); }
.icase__cell .arrowlink { margin-top: clamp(1rem, 2.6vh, 1.5rem); align-self: flex-start; }

/* The molten hairline that answers hover, borrowed from .tile::after and
   stretched across the full cell edge.

   INSIDE the padding box, not over the border (changed 2026-08-09). It used to
   sit at -1px on three sides so the ember REPLACED the grey rule. That stopped
   painting the moment `overflow:hidden` went on the cell for the photo motion
   above: overflow clips to the PADDING box, and -1px puts the line in the
   border band just outside it. Measured with casehair.js — 0 ember pixels on
   hover as shipped, 571 with overflow forced visible.

   Note it was NOT the leftover `clip-path: inset(0%)` from the scrub, which was
   the obvious suspect and is innocent: clip-path clips to the BORDER box, so it
   never touched this line. Same harness, states C and D, identical at 571.

   At 0 the ember sits directly above the grey rule instead of on top of it —
   1px lower than the original intent, and the only version of this that
   survives the clip the photograph needs. */
.icase__cell::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--ember);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform var(--d-s) var(--e-out);
}
.icase__cell:hover::after,
.icase__cell:focus-within::after { transform: scaleX(1); }

@media (max-width: 900px) {
  .icase {
    grid-template-columns: 1fr;
    grid-template-areas: "lead" "b" "c" "d";
  }
}

/* ---------------------------------------------------------
   Reduced motion.
   The track never goes live, so the ledger above is already the end
   state. All that is left is to stop the two hairline sweeps.
   --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .icase__cell::after { transition: none; }
  .stour--live .stour__track { will-change: auto; }
}
