/* ============================================================================
   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); }
}

/* On a phone the hero has to stop short of the fold.

   A full-height hero on a 700px viewport is a beautiful photograph and nothing
   else: the traveller has to scroll before the site offers them anything to do.
   Capping it near half the viewport leaves the top of the trip finder on screen
   at first paint, which is the one control that starts a booking. */
@media (max-width: 781px){
  .hsc--full .hsc__slide{
    min-block-size: min(54vh, 26rem);
  }
}

/* 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);
}
