/* =========================================================
   Section redesign — About. See REDESIGN-BRIEF.md.
   Loads after pages.css so it can override the .tile/.g3
   rules it replaces. Scoped to this page only.

   Sections, in page order:
     0 phero  — the page hero    (archetype 5, full-bleed split)
     1 figs   — Who We Are        (archetype 6, counter band)
     2 creed  — Vision/Mission    (editorial statements)
     3 spine  — Why Trust GLD     (archetype 3, scroll-drawn spine)
     4 bento  — Our Facilities    (archetype 2, editorial bento)
     5 globe  — Global Presence   (archetype 1, interactive globe)
   ========================================================= */

/* =========================================================
   0 · HERO — "the first section is a bit boring, only text".

   .phero and .phero__* belong to the shared pages.css, which
   the other six pages use unchanged. Everything here is scoped
   behind .phero--plate so About can carry a photograph without
   any of that leaking sideways.

   Archetype 5 — alternating full-bleed split, ported from the
   homepage's .about band: copy in a column, photograph hard to
   the opposite edge, a scrim ramp doing the dividing instead
   of a border.
   ========================================================= */

/* The section's own padding moves onto the copy column so the plate can
   run the full height of the hero — top edge under the header, bottom
   edge flush against the molten .seam. A photo that stops 5rem short of
   the seam is a rectangle on a background; one that touches it is the
   band's own surface. */
.phero--plate { padding: 0; }

.phero--plate .phero__inner {
  padding-top: calc(var(--nav-h) + clamp(3.4rem, 9vh, 6rem));
  padding-bottom: clamp(3rem, 7vh, 5rem);
}

.phero__plate {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--navy-900);
  isolation: isolate;
}

/* Oversized and offset so the scroll parallax has somewhere to travel
   without ever exposing an edge. object-position holds the pour itself
   near the middle of the crop at every aspect ratio. */
.phero__img {
  position: absolute;
  top: -7%; left: 0;
  width: 100%; height: 114%;
  object-fit: cover;
  object-position: 48% 44%;
  /* The homepage's .about__img grade — one stop under .ph--live, because
     this surface carries the fixed header and a caption over it. */
  filter: saturate(1) brightness(.86) contrast(1.06);
  will-change: transform;
}

/* Three ramps, each doing a job:
   1 the header is transparent until it sticks, so the top of the plate has
     to stay navy or the nav links sit on a furnace;
   2 the left edge dissolves into the copy column instead of butting it;
   3 a bed under the caption. */
.phero__grade {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, var(--navy-900) 0,
                    rgba(6, 21, 41, .92) calc(var(--nav-h) * .5),
                    rgba(6, 21, 41, .42) calc(var(--nav-h) + 1rem),
                    rgba(6, 21, 41, 0) calc(var(--nav-h) + 5rem)),
    linear-gradient(90deg, var(--navy-900) 0,
                    rgba(6, 21, 41, .55) 20%, rgba(6, 21, 41, 0) 58%),
    linear-gradient(0deg, rgba(6, 21, 41, .9) 0, rgba(6, 21, 41, 0) 24%);
}

/* The shutter. CSS lands it OPEN, so with JS off, gsap missing or motion
   refused the photograph is simply there; sec-about.js is what puts it
   back to scaleX(1) and wipes it away. */
.phero__shutter {
  position: absolute; inset: 0;
  z-index: 2;
  background: var(--navy-900);
  transform: scaleX(0);
  transform-origin: 100% 50%;
}

.phero__cap {
  position: absolute;
  left: clamp(1rem, 2.2vw, 1.8rem);
  bottom: clamp(.9rem, 2vh, 1.4rem);
  z-index: 3;
  display: flex; align-items: center; gap: .6rem;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--chrome);
}
.phero__cap::before {
  content: '';
  width: clamp(16px, 2vw, 26px); height: 1px;
  background: var(--molten);
}

/* ---------------------------------------------------------
   The split. Below 901px the plate becomes a band under the
   copy instead — putting a photograph above the h1 on a phone
   pushes the page's actual subject below the fold.
   --------------------------------------------------------- */
@media (min-width: 901px) {
  .phero--plate {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(320px, 40vw, 820px);
    min-height: clamp(430px, 64vh, 660px);
  }

  /* .phero__inner is also .wrap (max-width + auto margins). Inside a grid
     column those centre the copy in its cell instead of holding it on the
     site's 1440 grid, so both are dropped and the left padding is computed
     to land on the same line the wrap would have: at 1920 that is 312px,
     at 1440 it collapses to the plain gutter. */
  .phero--plate .phero__inner {
    grid-column: 1;
    max-width: none;
    margin: 0;
    align-self: center;
    padding-left: max(var(--gutter), calc(50vw - (var(--maxw) / 2) + var(--gutter)));
    padding-right: clamp(1.5rem, 3vw, 3rem);
  }

  .phero--plate .phero__plate { grid-column: 2; }

  /* Both rows pinned explicitly. The plate comes FIRST in the DOM (so the
     phone stack needs no `order`), and grid auto-placement is sparse: after
     an item lands in column 2 the cursor has moved past it, so the copy —
     which asks for column 1 — would be pushed down to a second row and the
     hero would render as a photo beside nothing, above a wall of text
     beside nothing. */
  .phero--plate .phero__inner,
  .phero--plate .phero__plate { grid-row: 1; }

  /* Heat line on the join, drawn downward as the shutter opens.

     A pseudo-element cannot be handed to gsap, so it reads a custom
     property that sec-about.js animates on the plate. The fallback in
     var() is 1, which means no JS, no gsap, or a thrown timeline all leave
     a fully drawn rule rather than an invisible one. */
  .phero__plate::before {
    content: '';
    position: absolute; left: 0; top: 0; bottom: 0;
    width: 2px; z-index: 4;
    background: linear-gradient(180deg,
      rgba(255, 107, 26, 0) 0%, var(--molten) 18%,
      var(--ember) 58%, rgba(255, 107, 26, 0) 100%);
    transform: scaleY(var(--plate-rule, 1));
    transform-origin: 50% 0;
  }
}

/* ---------------------------------------------------------
   Stacked. The plate becomes a letterbox band directly under
   the header and the copy follows it.

   Why above the copy and not below: at 375x820 a hero with two
   ledes and two stacked buttons fills the whole first screen,
   so a plate underneath it was invisible until you scrolled —
   which leaves the phone with exactly the text-only hero this
   section exists to replace. 2:1 is short enough that the h1
   still starts well inside the first screen.
   --------------------------------------------------------- */
@media (max-width: 900px) {
  .phero--plate .phero__inner {
    padding-top: clamp(1.8rem, 4.5vh, 2.8rem);
  }
  .phero__plate {
    aspect-ratio: 2 / 1;
    /* Clear of the fixed header rather than under it. At this width the
       band is only ~190px tall, and a top ramp strong enough to protect the
       nav would scrim most of the photograph away. */
    margin-top: var(--nav-h);
  }
  /* No copy beside it here, so the left ramp only muddies the photograph. */
  .phero__grade {
    background:
      linear-gradient(180deg, rgba(6, 21, 41, .5) 0, rgba(6, 21, 41, 0) 26%),
      linear-gradient(0deg, rgba(6, 21, 41, .88) 0, rgba(6, 21, 41, 0) 34%);
  }

  /* The heat line turns through 90 degrees: on the stack the join is the
     plate's bottom edge, not its left. Same --plate-rule driver, so there is
     still only one thing for the script to animate. */
  .phero__plate::before {
    content: '';
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 2px; z-index: 4;
    background: linear-gradient(90deg,
      rgba(255, 107, 26, 0) 0%, var(--molten) 16%,
      var(--ember) 58%, rgba(255, 107, 26, 0) 100%);
    transform: scaleX(var(--plate-rule, 1));
    transform-origin: 0 50%;
  }
}

/* =========================================================
   1 · FIGURES — "Who We Are". Was four .tile boxes in a .g4.
   These are numbers, so they are set as numbers.
   ========================================================= */

.figs {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: clamp(2rem, 5vh, 3.4rem) 0 0;
  padding: 0;
  border-top: 1px solid var(--rule-l);
}

.fig {
  padding: clamp(1.1rem, 2.4vw, 1.8rem) clamp(.9rem, 2vw, 1.6rem)
           clamp(1.1rem, 2.4vw, 1.8rem) 0;
  border-right: 1px solid var(--rule-l);
}
.fig:last-child { border-right: 0; }

/* Inline, not flex, and the separator is a REAL space in the markup.

   Flex with a `gap` was the first attempt and it renders identically, but it
   drops the space from the text content: the accessible name came out as
   "400,000sq. ft." and a screen reader reads that as one token. Inline
   children on the shared baseline give the same picture and keep the string
   correct; `white-space: nowrap` on the parent is then what guarantees the
   figure can never break, at that space or anywhere else. */
.fig__n {
  display: block;
  white-space: nowrap;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.7rem, 1rem + 2.1vw, 3rem);
  line-height: 1.04;
  letter-spacing: -.03em;
  color: var(--ink);
  /* The counter rewrites this text every frame; tabular figures stop the
     band juddering as digit widths change on the way up. */
  font-variant-numeric: tabular-nums;
}

/* 0.42em is the size that makes "400,000 sq. ft." fit a quarter-width
   column at every breakpoint — the unit was 3.0em of advance at full size
   and is 1.3em here. Slate rather than ink so it reads as a unit hanging
   off the figure, which is also what keeps all four cells looking like one
   family when only one of them carries a unit.

   inline-block because `transform` does not apply to a non-replaced inline
   box; without it the nudge onto the numeral's optical baseline is silently
   ignored. */
.fig__u {
  display: inline-block;
  font-family: var(--f-body);
  font-weight: 500;
  font-size: .42em;
  letter-spacing: .01em;
  color: var(--slate);
  transform: translateY(-.12em);
}

.fig__l {
  display: block;
  margin-top: .5rem;
  font-size: var(--fs-small);
  color: var(--slate);
  max-width: 18ch;
}

/* Two columns from 1040 rather than 860. Four columns between those widths
   is where the figure column gets tight enough that even the reduced unit
   has to fight for room, and the labels wrap to three lines. */
@media (max-width: 1040px) {
  .figs { grid-template-columns: repeat(2, 1fr); }
  .fig:nth-child(2) { border-right: 0; }
  .fig:nth-child(-n+2) { border-bottom: 1px solid var(--rule-l); }
}
@media (max-width: 420px) {
  .figs { grid-template-columns: 1fr; }
  .fig { border-right: 0; border-bottom: 1px solid var(--rule-l); }
  .fig__l { max-width: none; }
}

/* =========================================================
   2 · CREED — Vision / Mission / Values.
   Was two boxes plus a box containing a grid of lists.
   ========================================================= */

.creed {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.6rem, 4vw, 3.4rem);
  margin-top: clamp(1.4rem, 3vh, 2.2rem);
}

.creed__item {
  padding-left: clamp(1rem, 2vw, 1.6rem);
  border-left: 1px solid var(--rule-d);
}

.creed__tag {
  display: block;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--molten);
  margin-bottom: .8rem;
}

/* The one place on the page where the company speaks in its own voice, so
   it is set larger and lighter than body copy rather than filed in a card. */
.creed__say {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 300;
  font-size: clamp(1.05rem, .95rem + .55vw, 1.45rem);
  line-height: 1.45;
  letter-spacing: -.01em;
  color: var(--chrome);
  max-width: 34ch;
}

.values {
  margin-top: clamp(2rem, 5vh, 3.2rem);
  padding-top: clamp(1.2rem, 3vh, 1.8rem);
  border-top: 1px solid var(--rule-d);
}

.values__tag {
  display: block;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--steel-dim);
  margin-bottom: 1rem;
}

/* A row of marks, not three columns of bulleted lists inside a card. */
.values__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .55rem clamp(1rem, 2.4vw, 2rem);
}

.values__list li {
  position: relative;
  padding-left: 1.05rem;
  font-size: var(--fs-small);
  color: var(--steel);
}
.values__list li::before {
  content: '';
  position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px;
  background: var(--molten);
}

@media (max-width: 760px) {
  .creed { grid-template-columns: 1fr; gap: 1.6rem; }
}

/* =========================================================
   3 · SPINE — "Why Customers Trust GLD".
   Was five boxes in a three-column grid, orphaning two.
   ========================================================= */

.spine {
  position: relative;
  margin-top: clamp(1.4rem, 3vh, 2.2rem);
  padding-left: clamp(2.6rem, 6vw, 4.6rem);
}

.spine__list { list-style: none; margin: 0; padding: 0; }

/* The rail lives in the gutter the list's padding leaves for it. */
.spine__rail {
  position: absolute;
  left: clamp(.9rem, 2.2vw, 1.7rem);
  top: .6rem; bottom: .6rem;
  width: 1px;
  background: var(--rule-d);
}
.spine__fill {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--molten), var(--ember));
  transform: scaleY(0);
  transform-origin: 50% 0;
}

.spine__row {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 clamp(.9rem, 2vw, 1.5rem);
  padding: clamp(1rem, 2.4vh, 1.5rem) 0;
  border-bottom: 1px solid var(--rule-d);
}
.spine__row:last-child { border-bottom: 0; }

/* The node on the rail. Positioned back into the gutter from the row's own
   left edge, so it stays on the rail at every clamp breakpoint. */
.spine__row::before {
  content: '';
  position: absolute;
  left: calc(clamp(.9rem, 2.2vw, 1.7rem) - clamp(2.6rem, 6vw, 4.6rem) - 4px);
  top: calc(clamp(1rem, 2.4vh, 1.5rem) + .5em);
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--navy-900);
  border: 1px solid var(--rule-d2);
  transition: background var(--d-s) var(--e-out),
              border-color var(--d-s) var(--e-out),
              transform var(--d-s) var(--e-out);
}
.spine__row.is-on::before {
  background: var(--molten);
  border-color: var(--molten);
  transform: scale(1.35);
}

.spine__no {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .16em;
  color: var(--steel-dim);
  padding-top: .35em;
  transition: color var(--d-s) var(--e-out);
}
.spine__row.is-on .spine__no { color: var(--molten); }

.spine__body h3 {
  margin: 0 0 .35rem;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  letter-spacing: -.015em;
  color: var(--white);
}
.spine__body p {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--steel);
  max-width: 52ch;
}

/* =========================================================
   4 · BENTO — "Our Facilities".
   Was five boxes in a three-column grid. Then one photograph
   and four written cards. From 2026-09-09 it is four
   photographs and one written cell, which is a different
   layout problem and got a different layout.

   WHY THE PROPORTIONS MOVED. A box drawn for three lines of
   type is the wrong box for a picture: the old supporting
   cells were about 190px tall, and a photograph in one of
   those is a letterboxed strip nobody reads as a photograph.
   So the tracks were rebalanced around the pictures rather
   than the pictures being poured into the old tracks.

   Five unequal tracks, two bands, and — this is the point —
   three vertical splits that deliberately DO NOT line up:

     "lead lead lead melt melt"     ~61% | ~37%
     "lab  lab  ware ware note"     ~41% | ~34% | ~21%

   No repeat(n, 1fr) anywhere and no two cells the same width,
   because that pattern is exactly what this section was
   rebuilt to get away from. Order is preserved as well: read
   left to right, top to bottom, the cells come out 01 02 03
   04 05, so the visual sequence and the DOM sequence agree
   and the numbers are not fighting the layout.

   HEIGHTS ARE THE PHOTOGRAPH'S, NOT THE CELL'S — see
   .bento__fig. Cells stretch to their row; figures do not.
   ========================================================= */

.bento {
  display: grid;
  grid-template-columns: 1.53fr 1.27fr 1.33fr 1fr 1.53fr;
  grid-template-areas:
    "lead lead lead melt melt"
    "lab  lab  ware ware note";
  gap: clamp(.9rem, 1.8vw, 1.5rem);
  margin-top: clamp(1.6rem, 4vh, 2.4rem);
}

.bento__cell {
  display: flex;
  flex-direction: column;
  border-top: 2px solid var(--rule-l2);
  background: var(--white);
  /* The figure rests at scale 1.06 and drifts inside that headroom for as
     long as the band is on screen (js/sec-about.js facilities()). Without
     this the picture crosses the card edge onto the paper band. */
  overflow: hidden;
  transition: border-color var(--d-s) var(--e-out),
              transform var(--d-s) var(--e-out);
}
.bento__cell:hover {
  border-top-color: var(--molten-ink);
  transform: translateY(-3px);
}

/* Placement and crop, one line each. --fig-ar is read by .bento__fig
   below; it is declared here because the shape belongs to the cell's
   position in the band, not to the figure component. */
.bento__cell--lead      { grid-area: lead; --fig-ar: 2 / 1; }
.bento__cell--process   { grid-area: melt; --fig-ar: 3 / 2; }
.bento__cell--lab       { grid-area: lab;  --fig-ar: 4 / 3; }
/* 5:4 rather than the file's native 4:3. The billet stack is a receding
   perspective and survives a 6% trim off the sides without losing anything,
   and the cell is the narrowest of the three photographic supports — at
   native ratio it finished ~120px short of its row and left a band of bare
   white under two lines of type. */
.bento__cell--store     { grid-area: ware; --fig-ar: 5 / 4; }
/* 05 has no figure today. The ratio is declared anyway so that dropping a
   .bento__fig in is genuinely a one-block edit — it lands at the same
   shape as the warehouse cell beside it with nothing else to change. */
.bento__cell--logistics { grid-area: note; --fig-ar: 4 / 3; }

/* ---------------------------------------------------------
   THE WINDOW MATCHES THE PHOTOGRAPH, NOT THE CELL.

   Same rule as .icase__cell--lead in sec-industries.css, and it is here
   for the same reason recorded there: a box whose height comes from a grid
   row will `cover`-crop in whichever direction the row happens to be
   wrong, and the picture quietly loses its ends with nothing on screen to
   say so. The four ratios are read off the four files — 2:1 trims sky and
   car park off the 1.59 plant elevation and keeps the whole building, 3:2
   keeps nearly all of the 16:9 extrusion line, and the two 4:3 shots are
   carried at native ratio and cropped by nothing at all.

   flex: 0 0 auto, so the figure never absorbs the slack a taller
   neighbouring cell creates. That slack lands under the copy inside a
   white card, where it reads as margin; inside the picture it would read
   as a different crop on every viewport.

   aspect-ratio on a grid-sized (therefore definite) width means the box
   exists at its full height before a single byte of the image arrives —
   the images are CSS backgrounds and never contribute to layout, so this
   band cannot shift.
   --------------------------------------------------------- */
.bento__fig {
  position: relative;
  flex: 0 0 auto;
  aspect-ratio: var(--fig-ar, 3 / 2);
  overflow: hidden;
}
.bento__fig .ph { position: absolute; inset: 0; }

/* No scrim, no wash, no opacity: nothing is set on top of these pictures.
   The caption sits BELOW the figure, so these slots carry no text-contrast
   debt and take the full .ph--live grade from css/main.css — the grade
   Daniel re-judged against real photographs on 2026-08-08 after the first
   one came out too dark. The only thing hover changes is warmth, and it
   restates the whole filter because filter replaces rather than composes.
   It has to be filter and not transform: facilities() scrubs a transform
   on this element the entire time the band is on screen, so a CSS hover
   transform would be overwritten every frame and silently do nothing. */
.bento__fig .ph { transition: filter var(--d-m) var(--e-out); }
.bento__cell:hover .bento__fig .ph--live,
.bento__cell:focus-within .bento__fig .ph--live {
  filter: saturate(1.04) brightness(1.03) contrast(1.06);
}

.bento__body {
  display: flex;
  flex-direction: column;
  padding: clamp(1.1rem, 2.2vw, 1.6rem);
}

.bento__no {
  display: block;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .16em;
  color: var(--molten-ink);
  margin-bottom: .7rem;
}
.bento__cell h3 {
  margin: 0 0 .4rem;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  letter-spacing: -.015em;
  color: var(--ink);
}
/* The lead is the anchor of the band and now sits over a 2:1 plate; at the
   shared h3 size it read as an ordinary cell with a large picture stuck on
   top of it. Same correction as .vcell--lead on Sustainability. */
.bento__cell--lead h3 { font-size: clamp(1.2rem, 1rem + .8vw, 1.7rem); line-height: 1.14; }
.bento__cell p {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--slate);
  max-width: 46ch;
}

/* ---------------------------------------------------------
   THE WRITTEN CELL — 05, Logistics.

   No logistics photograph has been supplied. The failure this avoids is a
   fifth white card standing empty beside four full ones, which does not
   read as a decision, it reads as an image that did not load. So 05 is not
   a photo cell missing its photo: it is the one cell in the band set as
   type. It inverts to the direction's own navy — the 80% this page spends
   most of its length in — takes the molten top rule instead of the grey
   one, anchors its copy at the foot of the panel, and draws a hairline at
   the head so it has a motion beat of its own rather than being the one
   cell that never moves.

   KEYED ON :not(:has(.bento__fig)), NOT ON THE MODIFIER CLASS. That is the
   whole handover: the day a logistics photograph arrives, the only edit is
   pasting a .bento__fig block into the article. Every rule below stops
   matching by itself, the cell reverts to paper, the drawn rule
   disappears, and nothing in this file or in js/sec-about.js has to be
   found and undone. The class stays because it carries grid-area and
   --fig-ar, both of which the photo version still wants.

   A browser without :has() keeps the plain white card — which is precisely
   what shipped before today. The degradation path is the old design, never
   a broken one.
   --------------------------------------------------------- */
.bento__cell:not(:has(.bento__fig)) {
  background: var(--navy-800);
  border-top-color: var(--molten);
}
.bento__cell:not(:has(.bento__fig)):hover { border-top-color: var(--ember); }
/* Ember rather than molten on this ground: 11.5px mono needs 4.5:1 and
   ember clears it comfortably on navy-800, which is what the token exists
   for. Steel body and white heading are both measured on this navy in
   css/tokens.css. */
.bento__cell:not(:has(.bento__fig)) .bento__no { color: var(--ember); }
.bento__cell:not(:has(.bento__fig)) p { color: var(--steel); }
/* Set at the lead's size, not the supporting cells'. Exactly the note on
   .vcell--lead in sec-sustainability.css: a cell that is tall because its
   neighbours carry pictures, with a caption-sized heading in it, reads as
   an ordinary cell with a hole above the words. The panel has to carry the
   weight its height implies. */
.bento__cell:not(:has(.bento__fig)) h3 {
  color: var(--white);
  font-size: clamp(1.2rem, 1rem + .8vw, 1.7rem);
  line-height: 1.14;
}

/* Number at the head, copy at the foot, the air between them deliberate
   rather than left over. auto margin instead of space-between because the
   heading and the paragraph have to stay together at the bottom; padding
   rather than margin below the number so the pair never collide when the
   cell is short (a phone, where the auto margin resolves to zero).

   The body has to GROW for that auto margin to have anything to absorb.
   Everywhere else .bento__body is content-height and the row's slack sits
   under it as card padding, which is right when a photograph is holding
   the top of the cell. Here there is no photograph, so unclaimed slack
   would just be a void below the copy — the exact "did this load?" reading
   the whole treatment exists to avoid. */
.bento__cell:not(:has(.bento__fig)) .bento__body { flex: 1 1 auto; }
.bento__cell:not(:has(.bento__fig)) .bento__no {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: auto;
  padding-bottom: clamp(1.2rem, 4vh, 2.2rem);
}
/* The head rule — the same device as .label::before on every other band in
   this direction: a hairline that DRAWS rather than appears. It defaults
   to scaleX(1), so with JS absent, GSAP blocked, or motion refused the
   rule is simply drawn and the panel looks finished. facilities() winds it
   back to 0 and plays it forward; nothing here starts in a broken state. */
.bento__cell:not(:has(.bento__fig)) .bento__no::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: currentColor;
  transform: scaleX(var(--rule, 1));
  transform-origin: 0 50%;
}

/* ---------------------------------------------------------
   Tablet. Two bands become three and the lead takes the full width: at
   this size 61% of the content box is around 500px, which stops being a
   lead and starts being a thumbnail. The narrow-to-wide reading of each
   row survives, and 05 stays the narrow cell it is on desktop.
   --------------------------------------------------------- */
@media (max-width: 1079px) {
  .bento {
    grid-template-columns: 1.35fr 1fr;
    grid-template-areas:
      "lead lead"
      "melt lab"
      "ware note";
  }
  /* Square here, 4:3 on desktop. The laboratory is now the narrow cell in
     its row, beside a wide picture and a three-line heading, so at 4:3 it
     finished ~150px short of the row and left a slab of bare white under
     two lines of type. The bench runs across the frame and a square crop
     loses nothing from it. Art direction per breakpoint, not one ratio
     forced through every width. */
  .bento__cell--lab { --fig-ar: 1 / 1; }
}

/* Phone. One column, and the two wide crops open up — a 2:1 plate is
   167px tall at 375px wide, which is a strip, not a photograph. */
@media (max-width: 640px) {
  .bento {
    grid-template-columns: 1fr;
    grid-template-areas: "lead" "melt" "lab" "ware" "note";
  }
  .bento__cell--lead    { --fig-ar: 3 / 2; }
  .bento__cell--process { --fig-ar: 4 / 3; }
  /* Back off the tablet square: in a single column it made the laboratory
     a head taller than everything above and below it for no reason — the
     square existed to fill a row it no longer shares with anyone. */
  .bento__cell--lab     { --fig-ar: 4 / 3; }
}

/* =========================================================
   5 · GLOBE — "Global Presence", interactive globe.
   ========================================================= */

.globe__layout {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: center;
  margin-top: clamp(1.6rem, 4vh, 2.6rem);
}

/* ---------------------------------------------------------
   The stage.

   aspect-ratio rather than a fixed height so the canvas has a
   stable box before JS runs — the globe is lazy-loaded, and
   without a reserved box the whole section would shift when it
   arrives. That shift is CLS, and it lands exactly when the
   user is reading.
   --------------------------------------------------------- */
.globe__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  max-width: 620px;
  margin-inline: auto;
  touch-action: pan-y;   /* let the page scroll; drag is horizontal */
}

.globe__canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}
.globe__stage.is-dragging .globe__canvas { cursor: grabbing; }

/* Only ever shown once the globe is actually live and drivable. */
.globe__hint {
  position: absolute; left: 50%; bottom: 2%;
  transform: translateX(-50%);
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--steel-dim);
  opacity: 0;
  transition: opacity var(--d-m) var(--e-out);
  pointer-events: none;
}
.globe__stage.is-live .globe__hint { opacity: 1; }
.globe__stage.is-live:hover .globe__hint,
.globe__stage.is-dragging .globe__hint { opacity: 0; }

.globe__lede {
  color: var(--steel);
  font-size: var(--fs-body);
  max-width: 46ch;
  margin: 0 0 clamp(1.4rem, 3vh, 2.2rem);
}

/* ---------------------------------------------------------
   The regions.

   Deliberately NOT a card. The old version was three bordered
   boxes side by side; this is a single stacked list sharing one
   hairline, with a molten marker that travels to the active row.
   One object instead of three, which is the whole point.
   --------------------------------------------------------- */
/* Eight rows, not three (round 2, item 9): the three original regions plus
   five customer markets. A single stacked column of eight runs to roughly
   1,000px beside a 620px globe, so the register reflows into as many
   columns as its container can hold — auto-fit, not a breakpoint, because
   this list sits in a column whose width depends on the globe beside it AND
   on whether reduced motion has removed the globe entirely.

   The hairline moved with it. It used to be one border-top on the <ul> plus
   a border-bottom per row; in a two-column grid that leaves the second
   column's first row with no rule above it. Now every row draws its own top
   rule and the <ul> closes the register at the bottom — identical in one
   column, correct in two.

   Column-gap only. A row-gap would break the rules into rungs. */
.globe__regions {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  column-gap: clamp(1.2rem, 2.4vw, 2.4rem);
  border-bottom: 1px solid var(--rule-d);
}

.reg {
  position: relative;
  border-top: 1px solid var(--rule-d);
}

/* The travelling marker. Scales from 0 on the left edge, so the
   active row reads as "selected on the globe" rather than
   "hovered in a menu". */
.reg::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--molten);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform var(--d-s) var(--e-out);
}
.reg.is-active::before { transform: scaleY(1); }

.reg__btn {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  width: 100%;
  padding: clamp(.95rem, 2vw, 1.3rem) 0 .35rem clamp(.9rem, 2vw, 1.4rem);
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: padding-left var(--d-s) var(--e-out);
}
.reg:hover .reg__btn,
.reg.is-active .reg__btn { padding-left: clamp(1.3rem, 2.6vw, 1.9rem); }

.reg__tag {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--steel-dim);
  transition: color var(--d-s) var(--e-out);
}
.reg.is-active .reg__tag { color: var(--molten); }

.reg__name {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  letter-spacing: -.015em;
  color: var(--white);
}

.reg__body {
  margin: 0;
  padding: 0 0 clamp(.95rem, 2vw, 1.3rem) clamp(.9rem, 2vw, 1.4rem);
  color: var(--steel);
  font-size: var(--fs-small);
  max-width: 44ch;
  transition: padding-left var(--d-s) var(--e-out);
}
.reg:hover .reg__body,
.reg.is-active .reg__body { padding-left: clamp(1.3rem, 2.6vw, 1.9rem); }

/* ---------------------------------------------------------
   Responsive
   --------------------------------------------------------- */
/* The list needs more of the row than it used to, and the globe needs less:
   .globe__stage is capped at 620px and centres itself, so narrowing its
   column costs nothing until the cap is reached. */
@media (min-width: 1100px) {
  .globe__layout { grid-template-columns: 1fr 1.22fr; }
}

@media (max-width: 900px) {
  .globe__layout { grid-template-columns: 1fr; gap: clamp(1.4rem, 4vw, 2.2rem); }
  .globe__stage { max-width: 420px; order: -1; }
}

@media (max-width: 560px) {
  .globe__stage { max-width: 320px; }
}

/* ---------------------------------------------------------
   Reduced motion.

   sec-about.js never loads three.js at all in this mode, so the
   stage would otherwise reserve a large empty square. Collapse
   it and let the regions carry the section on their own — they
   already hold the full content.
   --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .globe__stage { display: none; }
  .globe__layout { grid-template-columns: 1fr; }
  .reg::before { transition: none; }
  .reg__btn, .reg__body { transition: none; }

  /* The hero needs nothing reset — every one of its motion states is
     authored as the FINISHED state and sec-about.js is what winds them
     back to play. All that is left is to drop the compositor layer the
     parallax would have used, since the parallax never runs. */
  .phero__img { will-change: auto; }

  /* Land every section in its finished state rather than its start state.
     The spine's rail is the one that matters: sec-about.js never scrubs it
     in this mode, so without this it would sit permanently at scaleY(0) and
     the section would look broken rather than calm. */
  .spine__fill { transform: scaleY(1); }
  .spine__row::before { background: var(--molten); border-color: var(--molten); }
  .spine__no { color: var(--molten); }
  .bento__cell, .spine__row::before, .spine__no { transition: none; }
  .bento__fig .ph { transition: none; }

  /* The facilities bento needs no state reset, and that is by construction
     rather than by luck. Every one of its motion states — the figures'
     clip wipe, their resting 1.06 and the drift on top of it, the copy
     lift, and the written cell's head rule — is authored so the CSS value
     IS the finished design, and facilities() in js/sec-about.js winds them
     back to play them forward. It takes the same bare `return` here that
     heroPlate() takes, and the band lands finished.

     Worth stating explicitly, because the opposite mistake has already
     been made in this file once: the globe collapses only under this media
     query while its JS also bails on `!hasWebGL()`, so a WebGL-off browser
     gets a reserved empty column that nothing here hides. Nothing in the
     bento is gated on anything but reduced motion, and its no-JS state is
     its finished state, so it cannot repeat that. */
}
