/* ============================================================================
   HERO STORY CAROUSEL
   One large hero, several stories, and visible navigation to every one of them.

   Brand-agnostic: every colour, font and duration below resolves through a
   --hsc-* variable that defaults to a core.css token. Re-point those variables
   under a theme class and the same component carries a different identity —
   see .hsc--teraxp at the foot of this file for the shape of that.

   Layout has two modes:
     .hsc--split  text left / media right   (DEFAULT — Thumb360's standing
                  site-wide hero rule: "text on the left, image or infographic
                  on the right, apply this for all hero sections")
     .hsc--full   full-bleed media with content over it (cinematic; for brands
                  whose hero rule allows it)
   ========================================================================= */

.hsc{
  --hsc-ink:          var(--t-carbon, #12100F);
  --hsc-ink-soft:     var(--t-graphite, #4A4744);
  --hsc-ground:       var(--t-white, #FFFFFF);
  --hsc-accent:       var(--t-red, #E31B2B);
  --hsc-rule:         var(--t-rule, rgba(18,16,15,.12));
  --hsc-rule-strong:  var(--t-rule-strong, rgba(18,16,15,.24));

  /* The project's motion system tops out at 400ms (--dur-max). The brief suggested
     350–700ms; where the two disagree the project's token wins, per §8. */
  --hsc-dur:          var(--dur-max, 400ms);
  --hsc-dur-nav:      var(--dur, 200ms);
  --hsc-ease:         var(--ease, cubic-bezier(.22,.61,.36,1));

  /* Overwritten from data-interval by the script. Drives the progress bar, and the
     progress bar drives slide advancement — there is no JS interval timer. */
  --hsc-interval:     8000ms;

  position: relative;
  color: var(--hsc-ink);
}

/* ---------------------------------------------------------------- viewport */
/* Every slide occupies the same grid cell, so the carousel is always as tall as
   its tallest story and never reflows when the slide changes. */
.hsc__viewport{
  display: grid;
  grid-template-areas: "slide";
}
.hsc__slide{
  grid-area: slide;
  min-inline-size: 0;
}

/* Inactive slides: visibility (not just opacity) so their links and buttons leave
   the tab order in every browser, with `inert` doing the same for the a11y tree. */
.hsc__slide{
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--hsc-dur) var(--hsc-ease),
              visibility 0s linear var(--hsc-dur);
}
.hsc__slide.is-active{
  opacity: 1;
  visibility: visible;
  transition: opacity var(--hsc-dur) var(--hsc-ease), visibility 0s;
}

/* Before the script runs, the first slide must already be readable — the markup is
   the content, the carousel is the enhancement. */
.hsc:not(.is-ready) .hsc__slide{ opacity: 1; visibility: visible; }
.hsc:not(.is-ready) .hsc__slide ~ .hsc__slide{ display: none; }
.hsc:not(.is-ready) .hsc__nav,
.hsc:not(.is-ready) .hsc__controls{ display: none; }

/* ------------------------------------------------------------ split layout */
.hsc--split .hsc__slide{
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (max-width: 899.98px){
  .hsc--split .hsc__slide{
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 2.5rem);
  }
  /* Mobile is not a shrunk desktop: the picture leads, the words follow. */
  .hsc--split .hsc__media{ order: -1; }
}

.hsc__media{ min-inline-size: 0; }
.hsc__media img,
.hsc__media video{
  inline-size: 100%;
  block-size: auto;
  display: block;
  object-fit: cover;
  object-position: var(--hsc-focal, 50% 50%);
}
.hsc--split .hsc__media img,
.hsc--split .hsc__media video{
  aspect-ratio: 4 / 3;
  border-radius: 2px;
}

/* -------------------------------------------------------- full-bleed layout */
.hsc--full .hsc__slide{
  position: relative;
  display: grid;
  align-items: end;
  min-block-size: clamp(30rem, 68vh, 44rem);
  isolation: isolate;
}
.hsc--full .hsc__media{
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hsc--full .hsc__media img,
.hsc--full .hsc__media video{ block-size: 100%; }
/* Scrim, not decoration: it is what keeps the headline legible over any photograph. */
.hsc--full .hsc__slide::after{
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to top,
    rgb(18 16 15 / var(--hsc-overlay, .74)) 0%,
    rgb(18 16 15 / calc(var(--hsc-overlay, .74) * .55)) 42%,
    rgb(18 16 15 / 0) 78%);
}
.hsc--full .hsc__body{
  padding-block: clamp(2rem, 6vw, 4rem);
  color: #fff;
}
.hsc--full .hsc__title,
.hsc--full .hsc__desc,
.hsc--full .hsc__eyebrow{ color: inherit; }

/* -------------------------------------------------------------- slide body */
/* In the split layout the 7fr column already sets the measure — capping the body as
   well would re-break the composed headline that the hero was signed off on. Only the
   full-bleed variant, where there is no column, needs a cap. */
.hsc--full .hsc__body{ max-inline-size: 34ch; }

.hsc__title{ margin-block: 0 .5em; }
.hsc__desc{
  color: var(--hsc-ink-soft);
  margin-block: 0;
  max-inline-size: 46ch;   /* measure belongs on the prose, not on the whole stack */
}
.hsc--full .hsc__desc{ color: rgb(255 255 255 / .84); }

/* Content settles a beat after the media, which is what stops a crossfade reading
   as a slideshow. */
@media (prefers-reduced-motion: no-preference){
  .hsc.is-ready .hsc__slide > *{
    opacity: 0;
    transform: translateY(8px);
    transition: opacity var(--hsc-dur) var(--hsc-ease),
                transform var(--hsc-dur) var(--hsc-ease);
  }
  .hsc.is-ready .hsc__slide.is-active > *{
    opacity: 1;
    transform: none;
    transition-delay: 80ms;
  }
}

/* ------------------------------------------------------ story navigation */
/* The signature element: every story is named and directly reachable. */
.hsc__nav{
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0;
  margin-block-start: clamp(.875rem, 2vw, 1.375rem);
  border-block-start: 1px solid var(--hsc-rule);
}

.hsc__story{
  position: relative;
  display: block;
  inline-size: 100%;
  text-align: start;
  padding-block: 1rem 1.05rem;
  padding-inline: 0 1.25rem;
  background: none;
  border: 0;
  border-block-start: 1px solid transparent;   /* reserved so nothing shifts on activation */
  margin-block-start: -1px;
  color: var(--hsc-ink-soft);
  cursor: pointer;
  font: inherit;
  transition: color var(--hsc-dur-nav) var(--hsc-ease);
}
.hsc__story:hover{ color: var(--hsc-ink); }
.hsc__story[aria-selected="true"]{ color: var(--hsc-ink); }

.hsc__story-n{
  display: block;
  font-size: .75rem;
  letter-spacing: .12em;
  font-weight: 500;
  color: var(--hsc-ink-soft);
  margin-block-end: .35rem;
  font-variant-numeric: tabular-nums;
  transition: color var(--hsc-dur-nav) var(--hsc-ease);
}
.hsc__story[aria-selected="true"] .hsc__story-n{ color: var(--hsc-accent); }

.hsc__story-t{
  display: block;
  font-size: clamp(.9rem, 1.05vw, 1rem);
  line-height: 1.25;
  font-weight: 400;
  transition: font-weight var(--hsc-dur-nav) var(--hsc-ease);
}
/* Weight is the active signal, in a brand whose whole type system is built on
   thin-to-bold contrast. Colour alone would not carry it. */
.hsc__story[aria-selected="true"] .hsc__story-t{ font-weight: 700; }

/* Progress rail sits on the nav's top border, so the active item is underlined by
   time passing rather than by a static mark. */
.hsc__rail{
  position: absolute;
  inset-block-start: -1px;
  inset-inline: 0 1.25rem;
  block-size: 2px;
  background: var(--hsc-rule-strong);
  opacity: 0;
  overflow: hidden;
}
.hsc__story[aria-selected="true"] .hsc__rail{ opacity: 1; }
.hsc__bar{
  display: block;
  block-size: 100%;
  inline-size: 100%;
  background: var(--hsc-accent);
  transform: scaleX(0);
  transform-origin: left center;
}
.hsc__story[aria-selected="true"] .hsc__bar{ transform: scaleX(1); }

/* Autoplay: the bar IS the timer. animationend advances the slide, so pausing the
   animation pauses the carousel and there is no second source of truth. */
@media (prefers-reduced-motion: no-preference){
  .hsc.is-playing .hsc__story[aria-selected="true"] .hsc__bar{
    animation: hsc-fill var(--hsc-interval) linear forwards;
  }
}
.hsc.is-paused .hsc__story[aria-selected="true"] .hsc__bar{ animation-play-state: paused; }

@keyframes hsc-fill{
  from{ transform: scaleX(0); }
  to  { transform: scaleX(1); }
}

/* Static carousel (no autoplay, or reduced motion): the rail still marks the active
   story, it simply does not animate. */
.hsc:not(.is-playing) .hsc__story[aria-selected="true"] .hsc__bar{ transform: scaleX(1); }

@media (max-width: 719.98px){
  /* Horizontally scrollable rather than hidden — direct access to every story is the
     point of the component and must survive on a phone. */
  .hsc__nav{
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .hsc__nav::-webkit-scrollbar{ display: none; }
  .hsc__story{
    flex: 0 0 min(62vw, 15rem);
    scroll-snap-align: start;
  }
}

/* ------------------------------------------------------------- controls */
.hsc__controls{
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-block-start: 1rem;
}
.hsc__btn{
  display: inline-grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  padding: 0;
  background: none;
  border: 1px solid var(--hsc-rule-strong);
  border-radius: 50%;
  color: var(--hsc-ink);
  cursor: pointer;
  transition: border-color var(--hsc-dur-nav) var(--hsc-ease),
              background-color var(--hsc-dur-nav) var(--hsc-ease);
}
.hsc__btn:hover{
  border-color: var(--hsc-ink);
  background: var(--t-wash, rgba(18,16,15,.05));
}
.hsc__btn svg{ inline-size: 1rem; block-size: 1rem; }
.hsc__btn .hsc-when-paused{ display: none; }
.hsc.is-paused .hsc__btn .hsc-when-paused{ display: block; }
.hsc.is-paused .hsc__btn .hsc-when-playing{ display: none; }

/* Focus must stay visible on a dark photograph as well as on white. */
.hsc__story:focus-visible,
.hsc__btn:focus-visible{
  outline: 2px solid var(--hsc-accent);
  outline-offset: 2px;
}

/* --------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce){
  .hsc__slide,
  .hsc__slide.is-active,
  .hsc__story,
  .hsc__story-t,
  .hsc__btn{ transition: none; }
  .hsc__bar{ animation: none; }
  .hsc__story[aria-selected="true"] .hsc__bar{ transform: scaleX(1); }
}

/* ------------------------------------------------------------ theming hook */
/* The behaviour above is brand-neutral. A second brand re-points the variables and
   inherits every interaction, which is the reuse the component exists for. */
.hsc--teraxp{
  --hsc-accent: var(--tx-accent, #087D87);
  --hsc-ink:    var(--tx-ink, #12100F);
  --hsc-dur:    var(--tx-dur, 500ms);
}
