/* ==========================================================================
   Anti - Bands and containers
   How a long page gets its rhythm. Loaded after sections.css/pages.css so a
   tone can win over a component's own ground.
   ========================================================================== */

/* --- Container -------------------------------------------------------------
   Three widths, one gutter ladder. Anything wider than `wide` is a table that
   should scroll inside its own region, not a wider page. */

.container {
  width: 100%;
  max-width: var(--container-default);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

.container--narrow { max-width: var(--container-narrow); }
.container--wide   { max-width: var(--container-wide); }

@media (min-width: 640px) { :root { --container-pad: var(--space-6); } }
@media (min-width: 1024px) { :root { --container-pad: var(--space-8); } }

/* --- Band rhythm -----------------------------------------------------------
   One padding ladder for every band, so sections never drift out of step
   with each other. */

.section,
.band {
  padding-block: var(--space-16);
}

.section--tight { padding-block: var(--space-12); }

@media (min-width: 640px) {
  .section, .band { padding-block: var(--space-20); }
  .section--tight { padding-block: var(--space-16); }
}

@media (min-width: 1024px) {
  .section, .band { padding-block: var(--space-24); }
  .section--tight { padding-block: var(--space-20); }
}

/* --- Grounds ---------------------------------------------------------------
   A page of nothing but white and one grey is legible but flat: every section
   reads as equally important. Alternate deliberately.

   `mist` is the document default, so body carries it and `.band--mist` exists
   mainly to make an intentional return to it readable in the markup. */

.band--white { background-color: var(--ground-white); }
.band--mist  { background-color: var(--ground-mist); }
.band--sand  { background-color: var(--ground-sand); }

/* Dark bands re-point the semantic tokens rather than restyling each child,
   so any component built on --color-surface / --color-text / --color-border
   adapts to the ground without knowing it is on one. */

.band--brand,
.band--ink {
  --color-text:          var(--color-inverse-text);
  --color-text-muted:    var(--color-inverse-muted);
  --color-text-subtle:   var(--color-inverse-muted);
  --color-surface:       var(--ink-800);
  --color-surface-sunk:  var(--ink-800);
  --color-bg-alt:        var(--ink-800);
  --color-border:        var(--color-inverse-border);
  --color-border-strong: rgba(255, 255, 255, 0.22);
  --color-focus:         var(--color-accent);
  color: var(--color-inverse-text);
}

.band--brand { background-color: var(--ground-brand); }
.band--ink   { background-color: var(--ground-ink); }

/* On a dark ground the accent is the readable emphasis colour; the olive
   accent-text exists for light grounds only and would disappear here. */
.band--brand .hero__title em,
.band--ink .hero__title em,
.band--brand .step__num,
.band--ink .step__num { color: var(--color-accent); }

/* --- Seams -----------------------------------------------------------------
   Two bands of the same ground in a row would read as one section, so the
   rule between them is drawn only where the grounds actually match. */

.band--white + .band--white,
.band--mist + .band--mist,
.band--sand + .band--sand {
  border-top: 1px solid var(--color-border);
}


/* --- Marquee ---------------------------------------------------------------
   A scroll container, not a transformed track. The obvious marquee is a flex
   row translated by -50% on a CSS animation, but a transformed track is no
   longer scrollable: touch dragging, momentum, keyboard arrow-scrolling and -
   the one that matters - the WCAG 2.2.2 stop mechanism all stop working.
   This advances scrollLeft a few pixels a frame and keeps all of them. */

.marquee {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.marquee__track {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-behavior: auto;      /* the loop jump must not animate */
  flex-wrap: nowrap;
  justify-content: flex-start;
}
.marquee__track::-webkit-scrollbar { display: none; }

.marquee__track > * { flex: none; }

.marquee__toggle {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--color-inverse-border);
  border-radius: var(--radius-pill);
  color: var(--color-inverse-text);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease-out);
}
.marquee__toggle:hover { background-color: rgba(255, 255, 255, 0.1); }
.marquee__toggle svg { width: 0.9375rem; height: 0.9375rem; }

.marquee__icon-play { display: none; }
.marquee__toggle[aria-pressed="true"] .marquee__icon-pause { display: none; }
.marquee__toggle[aria-pressed="true"] .marquee__icon-play  { display: block; }

/* Nothing auto-scrolls under reduced motion, so the control has nothing to
   stop and is removed from the tab order rather than left as a dead button. */
@media (prefers-reduced-motion: reduce) {
  .marquee__toggle { display: none; }
}

/* The hero and the figures strip below it are one opening statement, so the
   same-ground seam is suppressed between them. */
.hero + .band--mist { border-top: 0; }

/* --- Back to top -----------------------------------------------------------
   Hidden until the page is long enough behind you to warrant it, so it never
   sits over content on a short screen. */

.to-top {
  position: fixed;
  right: var(--space-5);
  bottom: var(--space-5);
  z-index: 40;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-pill);
  background-color: var(--color-inverse-bg);
  color: var(--color-inverse-text);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease-out),
              opacity var(--duration-base) var(--ease-out),
              translate var(--duration-base) var(--ease-out);
}

.to-top[hidden] { display: none; }

/* Not shown yet: invisible, inert, and out of the tab order. */
.to-top {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.to-top[data-shown] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.to-top:hover { background-color: var(--ink-700); }
.to-top:active { translate: 0 1px; }
.to-top svg { width: 1.125rem; height: 1.125rem; }

@media (prefers-reduced-motion: no-preference) {
  .to-top { translate: 0 8px; }
  .to-top[data-shown] { translate: none; }
}

@media (min-width: 1024px) {
  .to-top { right: var(--space-8); bottom: var(--space-8); }
}

/* --- Photographic band -----------------------------------------------------
   Three things are handled here so call sites do not have to re-derive them:

   1. A solid brand ground sits underneath, so a slow or 404 image degrades to
      the brand tone rather than to an unreadable band of white text on white.
   2. The contrast work is done by a flat scrim, not a blur. `backdrop-filter`
      is the first thing to fail on an old Android browser, and when it fails
      it fails to *nothing* - taking the text's legibility with it.
   3. On phones and tablets the photograph is capped to a band at the top
      rather than stretched behind the copy. A 3:2 photograph asked to fill a
      tall narrow box is a 4x magnification of a vertical strip through the
      middle of it, which is rarely the part worth showing. */

.band--photo {
  position: relative;
  isolation: isolate;
  background-color: var(--ground-brand);

  --color-text:          var(--color-inverse-text);

  /* A photograph is not a known colour. Behind the brightest part of an image
     the 78% scrim resolves to roughly #415951, where the usual muted grey-green
     falls to 3.4:1 - readable on the dark bands, not here. Secondary text on a
     photograph gets a light tint instead, which holds 6:1 against that worst
     case and more against everything darker. */
  --color-text-muted:    #dfe8e1;
  --color-text-subtle:   #dfe8e1;

  /* The eyebrow pill is a light chip on light grounds; on a photograph it has
     to become glass, or it turns into light text on a light pill. */
  --color-bg-alt:        rgba(255, 255, 255, 0.14);
  --color-surface:       rgba(255, 255, 255, 0.08);
  --color-border:        var(--color-inverse-border);
  --color-border-strong: rgba(255, 255, 255, 0.28);
  --color-focus:         var(--color-accent);
  color: var(--color-inverse-text);
}

.photo-band__media {
  position: absolute;
  inset: 0 0 auto 0;
  height: 18rem;
  z-index: -2;
  overflow: hidden;
}

.photo-band__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The scrim only covers the photograph on narrow screens, because the rest of
   the band is already the solid ground. */
.photo-band__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: rgba(12, 42, 27, 0.78);
}

/* Push the copy clear of the photo band on narrow screens. */
.band--photo > .container { padding-top: 15rem; }

@media (min-width: 640px) {
  .photo-band__media { height: 24rem; }
  .band--photo > .container { padding-top: 21rem; }
}

@media (min-width: 1024px) {
  /* Wide enough for the photograph to sit behind everything without being
     magnified into abstraction. */
  .photo-band__media { inset: 0; height: auto; }
  .band--photo > .container { padding-top: 0; }
}

/* --- Media frames ----------------------------------------------------------
   Ratio boxes, so an image reserves its space before it loads and the page
   never jumps as photographs arrive. */

.media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
  background-color: var(--color-surface-sunk);
}

.media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: scale var(--duration-slow) var(--ease-out);
}

.media--wide     { aspect-ratio: 16 / 10; }
.media--video    { aspect-ratio: 16 / 9; }
.media--portrait { aspect-ratio: 4 / 5; }

/* A slow push-in on hover. Scale, not width: it composites, so it does not
   force layout on every frame. */
.card--interactive:hover .media img,
.article:hover .media img,
.link-card:hover .media img { scale: 1.05; }

@media (prefers-reduced-motion: reduce) {
  .media img { transition: none; }
  .card--interactive:hover .media img,
  .article:hover .media img,
  .link-card:hover .media img { scale: none; }
}
