/* ════════════════════════════════════════════════════════════════════
   case-saas.css — page CSS for the white-label SaaS case.
   Loaded third, after styles.css and case.css, scoped by .case-saas.

   Everything the SaaS case shows is a near-black, small-type product
   screen. The first build put those captures on the ink band as bare
   rectangles: their edges dissolved into the ground, the argument for
   each one floated in a void of empty column beside it, and the best
   asset on the page — the partner platform that comes out the other
   end — was hidden in a carousel below the fold of solution 01.

   So this file does three things: it frames every screen so it reads as
   a window rather than a paste, it binds each argument to the screen it
   belongs to, and it gives the two facts that actually sell the project
   — six stages, and $399 against $15,000 — a shape instead of a
   paragraph.
   ════════════════════════════════════════════════════════════════════ */

/* ── 1 · HERO ─────────────────────────────────────────────────────
   Two composed transparent images, each carrying its own corners and
   shadow like the DEX hero — so no border-radius and no box-shadow
   here, or the transparent margin draws a second rectangle behind them.

   They are exported on one canvas of identical size, so stacking the
   front one absolutely over the back one lines them up to the pixel and
   the back one still sizes the block. */
.case-saas .chero-vis{min-width:0}
.case-saas #hero .hero-mock{position:relative}
.case-saas #hero .hero-mock img{border-radius:0;box-shadow:none}
.case-saas #hero .hm-front{position:absolute;inset:0;width:100%;height:auto}

/* The point of splitting the file: the card is nearer, so it swings
   further and settles quicker than the screen behind it. One shared
   transform reading four per-layer variables — the entry animation on
   --s is the same for both, only the parallax differs. */
.case-saas #hero .hero-mock img{
  transform:
    rotateY(calc(var(--px) * var(--rot)))
    rotateX(calc(var(--py) * var(--tilt)))
    translate3d(calc(var(--px) * var(--shift)), calc(var(--py) * var(--lift)), 0)
    translateY(calc((1 - var(--s)) * 30px))
    scale(calc(.95 + .05 * var(--s)));
  transition:transform var(--dur) var(--ez);
}
.case-saas #hero .hm-back {--rot:-3deg;--tilt:1.8deg;--shift:7px; --lift:4px; --dur:.5s}
.case-saas #hero .hm-front{--rot:-7deg;--tilt:4.2deg;--shift:24px;--lift:14px;--dur:.3s}

@media(prefers-reduced-motion:reduce){
  .case-saas #hero .hero-mock img{transform:none;transition:none}
}

/* The composite is wide, but taking the width out of the copy column
   broke the headline onto five lines. So the visual takes it from the
   page instead: it runs past the right edge of the wrap, the way a
   product surface does on a trading landing, and the copy keeps the
   measure it was set for. */
@media(min-width:1000px){
  .case-saas .chero-grid{grid-template-columns:minmax(0,1fr) minmax(0,1.02fr)}
  .case-saas .chero-vis{margin-right:calc(var(--pad) * -1)}
}
@media(min-width:1340px){
  /* past the 1240 column the gutter is real space, not padding — let the
     mockup use it rather than centring in a wider empty column */
  .case-saas .chero-vis{margin-right:calc((100vw - var(--col)) / -2)}
}

/* ── 2 · BRIEF ────────────────────────────────────────────────────
   The thesis leads the chapter instead of closing it: at the bottom of
   three white boxes the sentence read as a footnote to a list, which is
   the wrong way round — the list is the evidence for the sentence. */
.case-saas #brief .brief-claim{
  background:var(--lime);color:var(--ink);border-radius:var(--radius-card);
  padding:clamp(24px,3.4vw,52px);
  box-shadow:0 12px 30px -16px rgba(120,160,20,.5);
  /* the same value .bento uses between its cards — the slab reads as the
     top row of that grid, so the two gaps have to be one gap */
  margin-bottom:clamp(10px,1.1vw,14px);
}
/* the measure is set so the sentence fills the slab in two or three
   lines — at 20ch it stacked into four and left the right half bare
   lime, which is the loudest empty space on the page */
.case-saas #brief .brief-claim p{
  font-size:clamp(22px,2.9vw,42px);letter-spacing:-.045em;line-height:1.08;
  font-weight:500;text-wrap:balance;max-width:44ch;
}
.case-saas #brief .brief-claim .lab-m{
  display:block;margin-bottom:clamp(14px,1.6vw,22px);color:rgba(9,10,11,.6);
}
/* The two lists under it are .bx cards, same as the Context bento in
   case-cr and case-dex — the card ground is what makes this chapter read
   as part of the family. */

/* ── 3 · RESEARCH: the price scale ────────────────────────────────
   The one number that decides whether a partner starts. As a sentence
   it was a claim; drawn to scale it is an argument you cannot misread,
   and it is the brightest thing in its viewport by design. */
.case-saas .scale{
  margin-top:clamp(32px,4vw,56px);
  border-top:1px solid var(--line);padding-top:clamp(26px,3vw,42px);
}
.case-saas .scale-row{
  display:grid;gap:6px 20px;align-items:baseline;
  grid-template-columns:minmax(0,1fr);
  padding-block:clamp(14px,1.6vw,20px);
}
.case-saas .scale-row + .scale-row{border-top:1px solid var(--line-2)}
/* the value column is fixed, not auto: with auto, "$399" and "$60,000"
   are different widths and the three tracks end at three different x —
   which silently destroys the only thing the row is for */
@media(min-width:760px){
  .case-saas .scale-row{grid-template-columns:minmax(150px,auto) minmax(0,1fr) 122px}
  /* only once there is a column to right-align against: stacked, a
     right-aligned figure under a left-aligned label just zigzags */
  .case-saas .scale-row b{text-align:right}
}
.case-saas .scale-row .lab-m{white-space:nowrap}
/* the bar is the measurement: 399 and 60 000 on one linear scale, so the
   lime one is genuinely 0.66% of the track and looks it */
.case-saas .scale-bar{
  position:relative;height:14px;border-radius:3px;background:var(--tint);
  overflow:hidden;min-width:60px;
}
.case-saas .scale-bar i{
  position:absolute;inset:0 auto 0 0;display:block;border-radius:3px;
  width:var(--w);background:var(--ink);
  transform:scaleX(0);transform-origin:left;
  transition:transform 1.1s var(--ez) .15s;
}
.case-saas [data-reveal].in .scale-bar i{transform:scaleX(1)}
/* Lime on the longest bar, on the user's call. It is the top of the
   scale, so it is the reference every other row is read against — and it
   keeps three solid black slabs out of a light section. */
.case-saas .scale-max i{background:var(--lime)}
.case-saas .scale-row b{
  font-size:clamp(19px,2vw,30px);letter-spacing:-.045em;font-weight:500;
  white-space:nowrap;font-variant-numeric:tabular-nums;
}
.case-saas .scale-note{
  margin-top:clamp(18px,2vw,26px);color:var(--muted);
  font-size:clamp(15px,1.2vw,19px);line-height:1.45;letter-spacing:-.02em;
  max-width:58ch;
}
/* em keeps the serif italic it gets everywhere else on a case page —
   this is the one clause the sentence turns on */
.case-saas .scale-note em{color:var(--ink)}
.case-saas .scale-note small{
  display:block;margin-top:10px;font-family:var(--mono);font-size:var(--t-lab);
  letter-spacing:.1em;color:var(--dim);
}
@media(prefers-reduced-motion:reduce){
  .case-saas .scale-bar i{transition:none;transform:scaleX(1)}
}

/* ════════════════════════════════════════════════════════════════
   4 · THE INK BAND — one media system for every screen on it
   ════════════════════════════════════════════════════════════════ */

/* Four chapters run back to back on one continuous ink ground. At the
   shared 120px the boundary between two of them is 240px of nothing,
   which on black reads as the page having stopped rather than as
   breathing. Trimmed only inside the band — the light chapters keep the
   site's rhythm. */
@media(min-width:900px){
  .case-saas #solutions .chap{padding-block:clamp(54px,5.8vw,86px)}
  .case-saas #solutions .chap-head{margin-bottom:clamp(26px,3vw,42px)}
}

/* A framed screen. The captures are near-black and the band is
   near-black, so without an inset ground and a hairline the screen has
   no edge — it reads as a hole in the page rather than a window into a
   product. Same object as .mcard, but the caption sits beside the shot
   instead of under it, which is what a wide 2.1:1 capture needs. */
/* centred, not top-aligned: the captures run 2.1:1 to 3.4:1 and the
   caption is three lines, so anchoring it to the top leaves a 250px
   hole under it. Against the middle of a framed screen the same text
   reads as a composition rather than as text that ran out. */
.case-saas .srow{
  margin:0;display:grid;gap:clamp(20px,2.4vw,40px);
  grid-template-columns:minmax(0,1fr);align-items:center;
  padding-top:clamp(28px,3.2vw,50px);margin-top:clamp(28px,3.2vw,50px);
  border-top:1px solid var(--line);
}
.case-saas .chap-cont > .srow:first-child,
.case-saas .chap-cont > .srow.no-rule{border-top:0;padding-top:0;margin-top:0}
@media(min-width:900px){
  .case-saas .srow{grid-template-columns:minmax(0,1.68fr) minmax(0,.82fr)}
}
.case-saas .sshot{
  background:#15171c;border-radius:var(--radius-card);
  padding:clamp(8px,.9vw,12px);
  box-shadow:0 1px 0 rgba(240,241,235,.07) inset,
             0 30px 60px -34px rgba(0,0,0,.9);
}
.case-saas .sshot img{
  width:100%;height:auto;display:block;border-radius:var(--radius-media);
}
/* caption: a mono index ties the argument to its screen, and the rule
   under it gives the short column a bottom edge so it stops looking
   like text that ran out */
.case-saas .srow figcaption .lab-m{
  display:flex;align-items:center;gap:10px;margin-bottom:16px;
}
.case-saas .srow figcaption .lab-m::before{
  content:"";width:6px;height:6px;border-radius:1px;background:var(--lime);flex:none;
}
.case-saas .srow figcaption b{
  display:block;font-size:clamp(18px,1.6vw,24px);font-weight:500;
  letter-spacing:-.04em;line-height:1.1;margin-bottom:12px;
}
.case-saas .srow figcaption p{
  color:var(--muted);font-size:var(--t-body);line-height:1.6;max-width:40ch;
}

/* The full-width screen that has to be read end to end — the wizard, the
   metrics dashboard, the partner platform. Two of the three carry no
   caption: their chapter head already says what the screen is for, and
   repeating it under the image was the same sentence twice. The wizard
   keeps one, because "resumable" is a behaviour a still frame cannot
   show. Caption goes wide under the shot, in two columns. */
.case-saas .fig-lead{margin:0}
.case-saas .fig-lead .sshot{padding:clamp(10px,1.1vw,16px)}
.case-saas .fig-lead figcaption{
  display:grid;gap:clamp(8px,1.4vw,32px);
  grid-template-columns:minmax(0,1fr);
  margin-top:clamp(16px,1.8vw,26px);
}
@media(min-width:900px){
  .case-saas .fig-lead figcaption{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr)}
}
.case-saas .fig-lead figcaption b{
  font-size:clamp(19px,1.8vw,27px);font-weight:500;letter-spacing:-.04em;
  line-height:1.1;
}
.case-saas .fig-lead figcaption p{
  color:var(--muted);font-size:var(--t-body);line-height:1.6;max-width:56ch;
}

/* ── the six stages, as a rail ────────────────────────────────────
   The whole economic case for a $249 product is that one person
   finishes it alone. A screenshot of step one cannot say "six stages,
   resumable"; six numbered cells can, and they carry their own state
   the way the sidebar in the product does. */
.case-saas .wsteps{
  display:grid;gap:1px;background:var(--line);
  border-radius:var(--radius-card);overflow:hidden;
  grid-template-columns:repeat(2,minmax(0,1fr));
  margin-bottom:clamp(28px,3.4vw,48px);
}
@media(min-width:660px){.case-saas .wsteps{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(min-width:1000px){.case-saas .wsteps{grid-template-columns:repeat(6,minmax(0,1fr))}}
.case-saas .wstep{
  background:var(--ink-1);padding:clamp(14px,1.5vw,20px);
  display:flex;flex-direction:column;gap:10px;min-height:112px;
}
.case-saas .wstep .n{
  font-family:var(--mono);font-size:var(--t-lab);letter-spacing:.14em;
  color:var(--dim);
}
.case-saas .wstep b{
  font-size:clamp(13px,1.05vw,15px);font-weight:500;letter-spacing:-.02em;
  line-height:1.2;color:var(--paper);
}
.case-saas .wstep span{
  font-size:12px;line-height:1.4;color:var(--muted);margin-top:auto;
}
/* one cell carries the accent — the step where the partner picks a price,
   which is the step the hero mockup is showing */
.case-saas .wstep-on{background:var(--lime)}
.case-saas .wstep-on .n{color:rgba(9,10,11,.55)}
.case-saas .wstep-on b{color:var(--ink)}
.case-saas .wstep-on span{color:rgba(9,10,11,.66)}

/* ── the partner platform, two screens in one slot ────────────────
   Both captures are near-square and 2880px wide. Stacked they ate
   1500px of column and the second was only ever seen by someone who
   kept scrolling; side by side they drop to 590px, which is where this
   much 11px UI type stops being readable. So they share one full-width
   slot and take turns, at exactly the size a single screen had.

   The slide is sized so the next one shows by about 15% of its own
   width: that sliver is the whole affordance — nothing says "there is
   more sideways" as plainly as a screen already half in the frame, and
   it means the carousel needs no buttons under it.

   Mechanics are CSS scroll-snap, so swipe, trackpad, keyboard and a
   dragged scrollbar all work with the script switched off. The script
   adds mouse drag only. */
/* The peek has to come out of somewhere. Taken out of the slide it cost
   14% of a screen that is already dense at full width, so it comes out
   of the page instead: the track runs to the right edge of the viewport
   the way the hero mockup does, and the sliver sits in the gutter. */
.case-saas .pcar{--pgap:clamp(12px,1.4vw,20px)}
@media(min-width:1000px){
  .case-saas .pcar{margin-right:calc(var(--pad) * -1)}
}
@media(min-width:1340px){
  .case-saas .pcar{margin-right:calc((100vw - var(--col)) / -2)}
}
.case-saas .pcar-track{
  display:grid;grid-auto-flow:column;
  /* W = s + gap + 0.15s  →  s = (W − gap) / 1.15 */
  grid-auto-columns:calc((100% - var(--pgap)) / 1.15);
  gap:var(--pgap);align-items:start;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  scrollbar-width:none;-ms-overflow-style:none;
  cursor:grab;
}
.case-saas .pcar-track::-webkit-scrollbar{display:none}
.case-saas .pcar-track:focus-visible{outline:2px solid var(--lime);outline-offset:6px}
.case-saas .pcar-slide{scroll-snap-align:start;min-width:0}
/* while a drag is in progress the snap has to be off, or every pointer
   move fights the browser trying to land on a snap point; putting it
   back on release is what makes the slide settle */
.case-saas .pcar-track.is-drag{
  cursor:grabbing;scroll-snap-type:none;user-select:none;scroll-behavior:auto;
}
.case-saas .pcar-hint{
  display:flex;align-items:center;gap:10px;
  margin-top:clamp(14px,1.6vw,20px);color:var(--dim);
}
.case-saas .pcar-hint::after{
  content:"";flex:1;height:1px;background:var(--line);
}

/* ── the payoff chapter ───────────────────────────────────────────
   Three short proofs under the partner platform, no card chrome: the
   band already has cards in it and a fourth grid of boxes would read as
   the page repeating itself. */
.case-saas .proof3{
  display:grid;gap:1px;background:var(--line);
  border-radius:var(--radius-card);overflow:hidden;
  grid-template-columns:minmax(0,1fr);margin-top:clamp(28px,3.2vw,48px);
}
@media(min-width:760px){.case-saas .proof3{grid-template-columns:repeat(3,minmax(0,1fr))}}
.case-saas .proof3 > div{background:var(--ink-1);padding:clamp(18px,2vw,28px)}
.case-saas .proof3 .lab-m{display:block;margin-bottom:12px}
.case-saas .proof3 b{
  display:block;font-size:clamp(16px,1.4vw,21px);font-weight:500;
  letter-spacing:-.035em;line-height:1.15;margin-bottom:8px;
}
.case-saas .proof3 p{color:var(--muted);font-size:13px;line-height:1.5}

/* ── the lime number, sized to its sentence ───────────────────────
   At full width the 3.1× slab was two-fifths lime and nothing else.
   Paired with the fact that explains it, the colour has a job. */
.case-saas .hit-pair{
  display:grid;gap:clamp(10px,1.1vw,14px);grid-template-columns:minmax(0,1fr);
  margin-top:clamp(30px,3.4vw,50px);align-items:stretch;
}
@media(min-width:860px){
  .case-saas .hit-pair{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}
}
.case-saas .hit-pair .hit{margin:0;align-content:center}
.case-saas .hit-pair .hit b{font-size:clamp(46px,5.4vw,84px)}
.case-saas .hit-pair .hit p{font-size:clamp(14px,1.1vw,17px);max-width:34ch}
.case-saas .hit-pair .hit-side{
  background:rgba(240,241,235,.055);border-radius:var(--radius-card);
  padding:clamp(20px,2.4vw,34px);display:flex;flex-direction:column;
  justify-content:center;gap:12px;
}
.case-saas .hit-pair .hit-side b{
  font-size:clamp(17px,1.5vw,22px);font-weight:500;letter-spacing:-.04em;line-height:1.15;
}
.case-saas .hit-pair .hit-side p{color:var(--muted);font-size:var(--t-body);line-height:1.55}

/* ── 2b · the plain-language anchor ───────────────────────────────
   An ink slab directly under the facts. It is the only place on the
   page that says, in that order and with no argument attached, what the
   product is, what we made, and who pays for one. The case read as
   incomprehensible without it: every chapter below assumes all three.

   Ink rather than cards because it has to interrupt — the reader is
   three light rows deep at this point and the eye needs somewhere to
   stop. Same 1px-gap construction as .wsteps: the container paints the
   rules, the cells paint the ground. */
.case-saas .what{
  display:grid;gap:1px;background:rgba(240,241,235,.15);
  border-radius:var(--radius-card);overflow:hidden;
  grid-template-columns:minmax(0,1fr);
  margin-top:clamp(40px,5vw,72px);
}
@media(min-width:860px){
  .case-saas .what{grid-template-columns:repeat(3,minmax(0,1fr))}
}
.case-saas .what > div{
  background:var(--ink);color:var(--paper);
  padding:clamp(22px,2.6vw,36px);
}
.case-saas .what .lab-m{display:block;margin-bottom:14px;color:rgba(240,241,235,.44)}
.case-saas .what b{
  display:block;font-size:clamp(17px,1.5vw,23px);font-weight:500;
  letter-spacing:-.04em;line-height:1.14;margin-bottom:10px;
}
.case-saas .what p{
  color:rgba(240,241,235,.64);font-size:var(--t-body);line-height:1.6;
}

/* ── Result: the growth loop ──────────────────────────────────────
   Same rail as the wizard stages, four cells instead of six. It is a
   loop, not a list, but drawing it as a ring costs a diagram nobody
   would read at 390px — the numbers plus "back to 01" in the copy do
   the same work. No lime cell here: the 40+ slab below it already has
   the one accent this viewport gets.
   ponytail: three columns at 660px would orphan the fourth cell, so the
   rail stays two-wide until it can go four-wide. */
@media(min-width:660px){
  .case-saas .wsteps-4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(min-width:1000px){
  .case-saas .wsteps-4{grid-template-columns:repeat(4,minmax(0,1fr))}
}
.case-saas #result .wsteps{margin-top:clamp(28px,3.4vw,48px)}
.case-saas .loop-lead{
  display:flex;align-items:center;gap:14px;
  margin:clamp(30px,3.6vw,52px) 0 clamp(14px,1.4vw,18px);
}
.case-saas .loop-lead::after{content:"";flex:1;height:1px;background:var(--line)}
.case-saas #result .wsteps{margin-top:0}

/* the h1 broke at the hyphen — "for white-" / "label builder" — which reads as
   two words. The compound is one word, so it gets to stay one. */
.case-saas #hero h1 .nb{white-space:nowrap}
