/* ============================================================
   The CRM tour: six screens, one journey.

   The homepage's CRM section is the reference (css/crm-spotlight.css,
   js/crm-spotlight.js) and this borrows its vocabulary rather than its code:
   a stepped copy column against one held stage, discrete beats, one driver,
   real state changes instead of a cross-fade between two pictures.

   What is live and what is a photograph:

     live   the browser chrome, its URL, the reload sweep that runs on every
            screen change, and the app's own nav rail with a pill that SLIDES
            from item to item. Moving between beats navigates the app.
     photo  the screen itself, a real 1800x1125 shot of the seeded CRM.

   The screenshots carry their own sidebar, so the frame CROPS it off at 20.5%
   of the source width and the live rail stands in its place. 20.5% rather than
   18.7% (the sidebar card's own right edge) because the app paints a thin
   scroll indicator in the gutter just past the card, and clipped to a sliver
   at the frame edge that reads as a rendering fault. 20.5% clears it and still
   leaves about 27px of the app's background between the rail and the first
   panel, which is the gap the app itself draws.

     visible band  0.795 of 1800 = 1431px wide against 1125 tall
     img width     100 / 79.5 = 125.79%
     img offset    -20.5 * 1.2579 = -25.79%
     frame ratio   1431 / 1125 = 1.272

   THE DEFAULT STATE IS THE FALLBACK. Without js/crm-tour.js the section is a
   plain column: the six screens listed, then the six blocks of copy, every
   heading and every bullet readable. `.crm-tour--live` is opt-in and is what
   makes the stage stick and the rail drive. Reduced motion still gets the
   live mode - the beats are worth having with motion off - it just gets them
   as cuts rather than transitions.
   ============================================================ */

/* site.css line 743 puts `padding:78px 0; background:var(--cloud)` on every
   main>section that is not named in a long :not() list. That list is in a file
   this page is not allowed to touch, and its specificity is roughly (0,30,2),
   so nothing short of !important reaches past it. Only the two box properties
   it sets are overridden here; everything else in this file is ordinary
   cascade. */
.crm-tour{
  width:100%;
  margin-inline:auto;
  padding:clamp(20px,3vw,44px) var(--gutter) clamp(60px,6vw,96px)!important;
  background:var(--mist)!important;
}

.crm-tour__grid{display:grid;gap:0}

/* ---------------- the copy column ---------------- */

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

.crm-tour__step{
  display:flex;
  align-items:center;
  gap:10px;
  margin:0 0 14px;
  font-size:12px;
  font-weight:800;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--navy-2);
}

.crm-tour__step em{
  font-style:normal;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-width:26px;
  height:22px;
  padding:0 7px;
  border-radius:999px;
  background:rgb(76 29 149 / .1);
  font-size:11px;
  letter-spacing:.06em;
}

.crm-tour__beat h2{
  max-width:15ch;
  margin:0 0 14px;
  font-size:clamp(2.1rem,3.2vw,3.2rem);
  line-height:.98;
  letter-spacing:-.035em;
}

.crm-tour__beat>p{
  max-width:46ch;
  margin:0;
  color:var(--muted);
  font-size:clamp(16px,1.2vw,18px);
  line-height:1.55;
}

.crm-tour__beat ul{
  margin:20px 0 0;
  padding:0;
  list-style:none;
  max-width:46ch;
}

.crm-tour__beat li{
  position:relative;
  padding:10px 0 10px 24px;
  border-bottom:1px solid var(--line);
  font-size:15px;
  font-weight:650;
}

/* Drawn tick, never a typed glyph. */
.crm-tour__beat li::before{
  content:"";
  position:absolute;
  left:1px;
  top:17px;
  width:9px;
  height:5px;
  border-left:2px solid var(--teal);
  border-bottom:2px solid var(--teal);
  transform:rotate(-45deg);
}

/* ---------------- the stage ---------------- */

.crm-tour__app{
  border-radius:16px;
  overflow:hidden;
  background:#131118;
  box-shadow:0 34px 70px rgb(15 5 40 / .3);
}

.crm-tour__chrome{
  position:relative;
  display:flex;
  align-items:center;
  gap:12px;
  padding:0 14px;
  height:38px;
  background:#1b1922;
  border-bottom:1px solid rgb(243 243 245 / .07);
}

.crm-tour__dots{display:flex;gap:6px;flex:none}
.crm-tour__dots i{
  width:9px;
  height:9px;
  border-radius:50%;
  background:rgb(243 243 245 / .16);
}

.crm-tour__url{
  margin:0;
  padding:4px 12px;
  border-radius:999px;
  background:rgb(243 243 245 / .06);
  color:rgb(243 243 245 / .62);
  font-size:12px;
  font-weight:600;
  letter-spacing:.01em;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

/* Stands in for the six-screen tour until the real walkthrough video is
   ready. The production recording will use the same widescreen frame. */
.crm-tour__video-placeholder{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:16px;
  aspect-ratio:16 / 9;
  background:#131118;
}

.crm-tour__video-play{
  display:flex;
  align-items:center;
  justify-content:center;
  width:64px;
  height:64px;
  border-radius:50%;
  background:rgb(243 243 245 / .08);
  color:rgb(243 243 245 / .55);
}

.crm-tour__video-play svg{margin-left:3px}

.crm-tour__video-placeholder p{
  margin:0;
  color:rgb(243 243 245 / .4);
  font-size:14px;
  font-weight:600;
  line-height:1.4;
  text-align:center;
}

/* The reload sweep. It runs on every screen change and it is the cheapest
   honest signal that a navigation happened rather than a picture swapped. */
.crm-tour__sweep{
  position:absolute;
  left:0;
  bottom:-1px;
  height:2px;
  width:0;
  background:var(--navy-2);
  opacity:0;
}

.crm-tour--live .crm-tour__app.is-loading .crm-tour__sweep{
  width:100%;
  opacity:1;
  transition:width .52s cubic-bezier(.22,.61,.36,1),opacity .12s linear;
}

.crm-tour__body{display:flex;align-items:stretch}

/* ---- the live nav rail ---- */

.crm-tour__rail{
  position:relative;
  flex:none;
  width:176px;
  padding:14px 10px;
  background:#17151d;
  border-right:1px solid rgb(243 243 245 / .05);
}

.crm-tour__rail-item{
  position:relative;
  z-index:1;
  display:flex;
  align-items:center;
  gap:11px;
  height:40px;
  padding:0 12px;
  border-radius:10px;
  color:rgb(243 243 245 / .5);
  font-size:13.5px;
  font-weight:650;
  transition:color .38s cubic-bezier(.22,.61,.36,1);
}

.crm-tour__rail-item svg{flex:none}
.crm-tour__rail-item b{font-weight:650}
.crm-tour__rail-item.is-active{color:#fff}

/* The pill is one element that MOVES between the six items. Six pills fading
   in and out would be six state changes; one that travels is a navigation. */
.crm-tour__pill{
  position:absolute;
  left:10px;
  top:14px;
  width:0;
  height:40px;
  border-radius:10px;
  background:rgb(76 29 149 / .62);
  box-shadow:inset 0 0 0 1px rgb(124 58 237 / .35);
  opacity:0;
}

.crm-tour--live .crm-tour__pill{
  /* Live, the pill is driven by a transform off the rail's own origin, so its
     resting offsets go to zero and JS owns both axes. */
  left:0;
  top:0;
  opacity:1;
  transition:transform .5s cubic-bezier(.22,.61,.36,1),width .5s cubic-bezier(.22,.61,.36,1),height .5s cubic-bezier(.22,.61,.36,1);
}

/* ---- the screens ---- */

.crm-tour__screens{
  position:relative;
  flex:1 1 auto;
  min-width:0;
  aspect-ratio:1431 / 1125;
  overflow:hidden;
  background:#131118;
}

.crm-tour__screen{margin:0}

.crm-tour__screen img{
  display:block;
  /* The crop: see the header note. max-width has to be released as well -
     site.css sets `img{max-width:100%}` globally, which silently clamped the
     125.79% back to 100% and rendered the shot uncropped and letterboxed. */
  width:125.79%;
  max-width:none;
  margin-left:-25.79%;
  height:auto;
}

/* ---------------- fallback: no JS ---------------- */
/* Six screens listed, then the copy. Everything readable, nothing hidden. */

.crm-tour:not(.crm-tour--live) .crm-tour__screens{
  aspect-ratio:auto;
  display:grid;
  gap:2px;
}

/* ---------------- live ---------------- */

.crm-tour--live .crm-tour__screen{
  position:absolute;
  inset:0;
  opacity:0;
  transform:translateY(2.5%) scale(.985);
  transform-origin:50% 0;
  pointer-events:none;
  transition:opacity .5s cubic-bezier(.22,.61,.36,1),transform .62s cubic-bezier(.22,.61,.36,1);
}

.crm-tour--live .crm-tour__screen.is-active{
  opacity:1;
  transform:none;
}

/* The outgoing screen leaves UPWARD while the incoming arrives from below.
   Both moving the same way would read as a carousel; opposed, it reads as one
   screen being replaced by the next. */
.crm-tour--live .crm-tour__screen.is-out{
  opacity:0;
  transform:translateY(-2%) scale(1.015);
}

/* ============================================================
   DESKTOP: copy left, stage held on the right
   ============================================================ */

@media (min-width:1001px){
  .crm-tour__grid{
    grid-template-columns:minmax(0,1fr);
    gap:0;
    align-items:start;
  }

  /* The stage is FIRST in the DOM so that the single-column phone layout gets
     it above the copy without an `order` that block layout would ignore.
     Here it is put back on the right. */
  .crm-tour__stage{order:1}

  .crm-tour--live .crm-tour__stage{
    position:sticky;
    /* The site header is fixed and 129px tall. 24px of air under it. */
    top:153px;
    align-self:start;
  }

  .crm-tour--live .crm-tour__app{max-width:980px}

  /* Each beat gets a viewport-ish run of scroll so exactly one of them owns
     the read line at a time. min-height rather than a fixed height: a beat
     that wraps to five lines on a narrow desktop must still fit its own box.

     The run is the SCROLL LENGTH, not where the words sit. Left to flow, a
     beat's copy crossed 660px of screen inside its own band and spent the last
     third of it cut off by the top of the window, which is how the heading of
     the beat you were reading ended up half behind the header. So the words
     are held by a sticky inner block instead: each one holds beside the stage
     for its whole band and is only carried off by the next beat's box, which
     is arriving at exactly that moment. */
  .crm-tour--live .crm-tour__beat{
    min-height:74vh;
    padding-block:clamp(24px,3vw,48px);
    opacity:.34;
    transition:opacity .45s cubic-bezier(.22,.61,.36,1);
  }

  .crm-tour--live .crm-tour__beat-inner{
    position:sticky;
    /* The header is fixed and 129px tall; the stage is held at 153 and runs to
       about 819. 260 puts the copy's optical centre on the stage's. */
    top:clamp(190px,26vh,260px);
  }

  .crm-tour--live .crm-tour__beat.is-active{opacity:1}

  /* The last beat needs room under it or the stage unsticks before its own
     screen has been read. */
  .crm-tour--live .crm-tour__beat:last-child{min-height:82vh}
}

/* ============================================================
   PHONE: the screen holds at the top, the copy walks past it
   ============================================================ */

@media (max-width:1000px){
  .crm-tour{padding:16px 20px 64px!important}
  .crm-tour__grid{gap:0}

  /* PHONE GEOMETRY, measured at 390x844 rather than guessed. The two held
     blocks have to tile the screen between them or a beat gets cut in half by
     the picture it belongs to, which is exactly what a first pass here did:
     the heading disappeared behind the frame while its own bullets sat under
     it.

       header bottom          ~52
       stage top               70
       chrome 32 + rail 46 + screen (350 / 1.272 = 275) + 16 of air = 369
       stage bottom           439
       copy holds at          452
       copy band              452 -> 844 = 392px

     The copy is then sized to live inside 392: the type steps down on the
     phone not for taste but because that is the room there is. */
  .crm-tour--live .crm-tour__stage{
    position:sticky;
    top:70px;
    z-index:2;
    /* The copy scrolls up BEHIND the held screen, so the stage needs its own
       ground and a little air under it or the first line of the next beat
       arrives half cut. */
    padding-bottom:16px;
    background:var(--mist);
  }

  /* Held too, in the band the stage leaves. Without this the copy simply flows
     and every beat spends part of its band split around the frame. */
  .crm-tour--live .crm-tour__beat-inner{
    position:sticky;
    top:452px;
  }

  /* Capped and centred, not full width. Everything below 1001px shares one
     geometry: the copy is held at a fixed 452 and that number is only right
     while the stage is a fixed height. Left to fill the column the app was
     660px tall at 768 and the copy held behind it. 360 is the 390px phone's
     own width less its gutters, so the phone is unchanged and the tablet
     simply stops growing. */
  .crm-tour--live .crm-tour__app{
    max-width:360px;
    margin-inline:auto;
    box-shadow:0 18px 38px rgb(15 5 40 / .26);
  }

  .crm-tour--live .crm-tour__beat-inner{max-width:520px;margin-inline:auto}

  /* Icons only. A 176px labelled rail against a 350px screen leaves the
     screenshot too narrow to read as a screen at all. */
  .crm-tour--live .crm-tour__rail{
    width:auto;
    display:flex;
    justify-content:space-between;
    gap:2px;
    padding:8px 8px;
    border-right:0;
    border-bottom:1px solid rgb(243 243 245 / .05);
  }

  .crm-tour--live .crm-tour__body{display:block}
  .crm-tour--live .crm-tour__rail-item{height:34px;padding:0 9px;gap:0}
  .crm-tour--live .crm-tour__rail-item b{display:none}
  .crm-tour--live .crm-tour__pill{height:34px}
  .crm-tour__chrome{height:34px;padding:0 12px;gap:10px}
  .crm-tour__url{font-size:11px;padding:3px 10px}

  /* 104svh per beat, and the number is solved rather than chosen. The copy is
     held at 452 by a sticky that is bounded by its own list item, so once the
     item's bottom edge arrives the copy stops being held and is dragged up
     behind the picture. That drag has to finish AFTER the next beat has taken
     over, or the beat you are reading walks up behind the screen it belongs
     to - which is precisely what 58svh did:

       copy height          ~380
       held while           liTop between (832 - L) and 452
     The drag that used to eat the end of every beat is dealt with in
     js/crm-tour.js, by handing over on the frame the drag would start rather
     than by making the list item taller - the drag term does not depend on
     this height. 96svh is simply long enough that the incoming copy has risen
     into the band and then held for about 480px before the next one is due.

     Only ONE beat is visible on the phone at a time: there is no room in a
     392px band for a dimmed neighbour, so the inactive ones are not dimmed,
     they are gone. */
  .crm-tour--live .crm-tour__beat{
    min-height:96svh;
    padding-block:0;
    opacity:0;
    transition:opacity .38s cubic-bezier(.22,.61,.36,1);
  }
  .crm-tour--live .crm-tour__beat.is-active{opacity:1}
  .crm-tour--live .crm-tour__beat:last-child{min-height:76svh}

  .crm-tour__step{margin-bottom:10px;font-size:11px}
  .crm-tour__beat h2{font-size:1.55rem;line-height:1;margin-bottom:10px;max-width:none}
  .crm-tour__beat>p{font-size:14.5px;line-height:1.5;max-width:none}
  .crm-tour__beat ul{margin-top:14px;max-width:none}
  .crm-tour__beat li{padding:7px 0 7px 22px;font-size:13.5px}
  .crm-tour__beat li::before{top:14px}
}

@media (prefers-reduced-motion:reduce){
  .crm-tour--live .crm-tour__screen,
  .crm-tour--live .crm-tour__beat,
  .crm-tour--live .crm-tour__pill,
  .crm-tour__rail-item{transition:none}
  /* The reload sweep is pure motion, and with the transition off it would just
     sit there as a drawn violet line for half a second. Not run at all. */
  .crm-tour--live .crm-tour__app.is-loading .crm-tour__sweep{
    width:0;
    opacity:0;
    transition:none;
  }
}

/* Nothing is dimmed with motion off: a reader who cannot use the transition to
   tell beats apart should not also be reading half-faded type. Desktop only -
   on the phone the beats share one band and hiding the inactive ones is what
   stops six of them landing on top of each other. */
@media (min-width:1001px) and (prefers-reduced-motion:reduce){
  .crm-tour--live .crm-tour__beat{opacity:1}
}

/* ---- Desktop canvas ceiling ------------------------------------------------
   The hero is positioned with clamps that all top out at roughly a 1630px
   viewport: left:clamp(56px,7.6vw,124px) plus the two font clamps. Past that
   the hero stopped responding while every content section kept centring in the
   1344px column, so the page lost its spine as the screen grew: measured on the
   homepage, the hero h1 sat 484px left of the sections below it at 2560, and
   924px left of them at 3440. The stages that size themselves off the viewport
   (%-based hero card, the journey gallery) kept growing at the same time.

   Cap the stages at one canvas and centre them. Nothing moves at or below
   1680px, which covers every laptop and most desktops. hero-film.js measures
   stage.clientWidth and crm-spotlight.js measures sticky.offsetWidth, so both
   recompute against the capped box rather than the window. */
.crm-tour__grid{
  width:min(100%,var(--canvas));
  margin-inline:auto;
}
