/* ===================== walkthrough card (.sc) =====================
   The five-step product panel. Three stories share this one component:

     - invoice autopilot, the DEFAULT panel on /, /demo and /demo-sb-form
     - submittal autopilot, /demo?utm_campaign=sub, cloned in from a <template>
     - forecasting, /demo-sb?utm_campaign=fcst, likewise. The only one that uses
       .sc-chart; see plans/plan-forecasting-variant.md for its height budget.

   Behaviour is assets/walkthrough-card.js. Sizing rationale is
   plans/plan-submittal-demo-card.md (the tiers) and
   plans/plan-invoice-walkthrough-card.md (the second story), read them before
   changing a number.

   ---- why this is its own stylesheet ----
   It used to live at the bottom of ad-landing.css. The homepage can't link that
   file (it styles html/body for the 100dvh one-screen shell), so the component
   moved out. Two consequences worth knowing:

   1. The palette is declared on `.sc` itself, not on :root. On the homepage
      there are no tokens to inherit; on the ad landings these shadow the
      identical :root values for the card's subtree only.
   2. Selectors are `.sc` (0,1,0), not `.demo.sc`. On the ad landings the card
      is `class="demo sc"` and `.demo` still supplies PLACEMENT, gutters,
      order:3 on mobile, max-width 480/420, the desktop box-shadow. `.sc` wins
      padding / gap / radius on source order, so this file MUST be linked after
      ad-landing.css. And `.sc` sets no margin and no max-width: the first would
      eat the demo pages' gutter, the second would stop the homepage card from
      filling its hero grid column.

   Four fixed geometry tiers. Width tier comes from the card's OWN rendered
   width, walkthrough-card.js sets data-w off a ResizeObserver, so the card is
   still right if it's dropped in a narrow column on a wide screen. Height tier
   is a real viewport query. Every total is measured against the /demo shell's
   height budget, which is the tightest place the card ships. */

.sc {
  /* ---- palette: ad-landing.css's :root, re-declared so this file stands alone ---- */
  --sc-bg: #0A0B0E;
  --sc-surface: #1A1D22;
  --sc-surface-2: #0F1114;
  --sc-border: #23262C;
  --sc-border-strong: #2E3238;
  --sc-amber: #F5A623;
  --sc-amber-hover: #FFB840;
  --sc-cyan: #13F5F5;
  --sc-ok: #2ECC71;
  --sc-sent: #7AB6F7;
  --sc-text-2: #E6E9ED;
  --sc-text-3: #C7CDD6;
  --sc-muted: #9BA3AF;
  --sc-muted-2: #6A707B;
  --sc-muted-3: #5A6068;
  --sc-grotesk: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --sc-mono: 'Space Mono', ui-monospace, monospace;

  /* tier 2, narrow, tall viewport. Total ~267 against a 300 budget @393x852. */
  --sc-pad-y: 15px;  --sc-pad-x: 17px;  --sc-gap: 11px;  --sc-radius: 16px;
  /* Body is sized to the tallest step plus a margin, not to the budget: the spare
     is what absorbs env(safe-area-inset-bottom) on a notched phone, which headless
     Chromium reports as 0 and a real iPhone does not. */
  /* 68, not the 76 the budget allows: step 3's title runs to three lines in the 345px
     band (iPhone 15) and only two at 364 (Pixel 8), and the pane is 1px over at 76. */
  --sc-body: 160px;  --sc-row: 32px;    --sc-rgap: 7px;   --sc-chart: 68px;
  /* 44px commit button at every tier, it's the one real tap target in the card */
  --sc-title: 13px;  --sc-label: 9px;   --sc-val: 10px;  --sc-btn: 44px;

  display: flex;
  flex-direction: column;
  flex: none;
  padding: var(--sc-pad-y) var(--sc-pad-x);
  gap: var(--sc-gap);
  border-radius: var(--sc-radius);
  background: var(--sc-surface);
  border: 1px solid var(--sc-border-strong);
  overflow: hidden;
  font-family: var(--sc-grotesk);

  /* ---- swipe ----
     Most of this card's traffic is mobile, where the step bars are a 16px target and
     a swipe is the gesture people actually reach for. `pan-y` is what makes that safe
     on the homepage, which scrolls: the browser keeps the vertical axis and hands us
     the horizontal one, so a swipe can never fight a scroll. Without it the browser
     may claim the gesture before `pointermove` ever fires.
     `user-select: none` because a mouse drag across a card that navigates on drag
     would otherwise also paint a text selection. It costs the ability to select the
     copy in here, which is a demo panel, not prose. */
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}

/* tier 1, narrow, short. The floor: 375x667, budget 227, this lands ~219.
   The 5px that bought the margin came out of padding and gap, never the body,
   steps 4 and 5 need all 150px of it for two rows plus a 44px tap target. */
@media (max-height: 700px) {
  .sc {
    --sc-pad-y: 11px; --sc-pad-x: 14px; --sc-gap: 7px;
    --sc-body: 150px; --sc-row: 30px;   --sc-rgap: 6px;   --sc-chart: 66px;
    --sc-title: 12px; --sc-val: 10px;
  }
}

/* tier 4, wide, tall. ~500 against 699 @1100x760. */
.sc[data-w="wide"] {
  --sc-pad-y: 26px; --sc-pad-x: 28px; --sc-gap: 18px; --sc-radius: 20px;
  --sc-body: 328px; --sc-row: 41px;   --sc-rgap: 10px;  --sc-chart: 160px;
  --sc-title: 17px; --sc-label: 11px; --sc-val: 12px; --sc-btn: 44px;
}

/* tier 3, wide, short. ~402 against 657 @1366x680. Must follow tier 4: same
   specificity, so source order is what makes the short viewport win. */
@media (max-height: 700px) {
  .sc[data-w="wide"] {
    --sc-pad-y: 18px; --sc-pad-x: 20px; --sc-gap: 12px;
    --sc-body: 278px; --sc-row: 38px;   --sc-rgap: 8px;   --sc-chart: 128px;
    --sc-title: 15px;
  }
}

/* ---- header line ---- */
.sc-hdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--sc-mono);
  font-size: var(--sc-label);
  letter-spacing: 1.5px;
  color: var(--sc-muted-2);
  white-space: nowrap;
}

.sc-job { overflow: hidden; text-overflow: ellipsis; }

.sc-actor {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: none;
  color: var(--sc-ok);
}

.sc-actor i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  animation: scPulse 1.8s ease-in-out infinite;
}

/* the human touches, the pill goes amber to say so */
.sc[data-actor="you"] .sc-actor { color: var(--sc-amber); }

/* ---- progress bar: the auto-advance timer ---- */
.sc-prog {
  height: 2px;
  flex: none;
  background: var(--sc-surface-2);
  border-radius: 2px;
  overflow: hidden;
}

.sc-prog i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--sc-amber);
}

/* ---- body: fixed height, every state, every step ----
   overflow:hidden means an over-tall pane clips silently rather than resizing the
   card, so tests/e2e asserts scrollHeight <= clientHeight on every step and state. */
.sc-body {
  flex: none;
  height: var(--sc-body);
  overflow: hidden;
}

.sc-step { display: none; flex-direction: column; gap: var(--sc-rgap); }
.sc-step.on { display: flex; }

/* The pane follows the finger during a swipe (walkthrough-card.js writes the inline
   transform) and eases back when the drag is released short of the threshold. No
   transition while the finger is down, or the pane lags behind it. `transform` never
   affects scrollHeight, so none of this touches the body-height gates. */
.sc-step { transition: transform .22s ease; }
.sc.is-drag .sc-step { transition: none; }

.sc-title {
  margin: 0;
  font-size: var(--sc-title);
  line-height: 1.28;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--sc-text-2);
}

.sc-rows { display: flex; flex-direction: column; gap: var(--sc-rgap); }

/* display:flex above outranks the UA's [hidden]{display:none}, so the pre/post
   swap on steps 4 and 5 needs this or both states render at once. */
.sc-rows[hidden] { display: none; }

/* ---- rows ----
   Label ellipses rather than wraps: a wrapped mono label is what inflates a row
   into two lines in the 420px band and quietly eats the body's height budget. */
/* flex:none + min-height:0 + overflow:hidden is what makes the row height actually
   fixed. Without it a single glyph can grow the row and blow the body's budget:
   ✓ (U+2713), ← (U+2190) and ▲ (U+25B2) fall outside the self-hosted Space Mono
   unicode-range, render in a fallback face with taller metrics, and min-height:auto
   lets that line box win over `height`. */
.sc-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: none;
  height: var(--sc-row);
  min-height: 0;
  overflow: hidden;
  line-height: 1;
  padding: 0 10px;
  background: var(--sc-surface-2);
  border: 1px solid var(--sc-border);
  border-radius: 8px;
  font-family: var(--sc-mono);
  font-size: var(--sc-val);
  color: var(--sc-muted);
  text-align: left;
  width: 100%;
}

/* min-width:0 or the label refuses to shrink below its content and the ellipsis
   never fires, which is how a mono label wraps to two lines in the 420px band. */
.sc-k { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-v { flex: none; white-space: nowrap; color: var(--sc-text-3); }

.sc-row.amber { border-color: rgba(245, 166, 35, .35); background: rgba(245, 166, 35, .12); }
.sc-row.amber .sc-v { color: var(--sc-amber); font-weight: 700; }
.sc-v.cy { color: var(--sc-cyan); }
.sc-v.ok { color: var(--sc-ok); }
.sc-v.sent { color: var(--sc-sent); }
.sc-v.am { color: var(--sc-amber); }

/* the mono chain line on submittals step 2 and the footnotes, full width, no well */
.sc-note {
  font-family: var(--sc-mono);
  font-size: var(--sc-val);
  line-height: 1.45;
  color: var(--sc-muted-2);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.sc-note.wrap { white-space: normal; }

/* ---- the chart pane (forecasting story) ----
   A second pane primitive next to .sc-row, and tokenised the same way for the same
   reason: .sc-body is a fixed height with overflow:hidden, so anything that isn't a
   known height is a pane that clips in silence at one tier, on one step.

   Budget for a chart pane is title + chart + 1 row narrow / 2 rows wide. There is no
   version of this that also carries a 44px .sc-cta at tier 1, 31 + 66 + 44 + gaps is
   already over the 150px body before a single row. That's why step 5 has no chart. */
.sc-chart {
  flex: none;
  height: var(--sc-chart);
  overflow: hidden;
  border-radius: 8px;
  background: var(--sc-surface-2);
  border: 1px solid var(--sc-border);
}

/* preserveAspectRatio="none" in the markup: the chart is decorative and stretches to
   whatever the tier gives it. Every stroked element carries vector-effect, or that
   non-uniform scale renders a 1px line at 3px on one axis. */
.sc-chart svg { display: block; width: 100%; height: 100%; }
.sc-chart path, .sc-chart line { fill: none; }

.sc-hist  { stroke: var(--sc-amber); stroke-width: 2; }
/* No static opacity on anything in here. The reduced-motion contract is "every mark is
   at full opacity once the animations are off", and the E2E suite asserts exactly that
a decorative .92 reads as a mark left mid-fade. Dim with stroke colour instead. */
.sc-fcast { stroke: var(--sc-amber); stroke-width: 2; stroke-dasharray: 5 4; }
.sc-ghost { stroke: var(--sc-muted-3); stroke-width: 1.5; stroke-dasharray: 2 3; }
.sc-now   { stroke: var(--sc-border-strong); stroke-width: 1; stroke-dasharray: 2 3; }
.sc-band > path { fill: var(--sc-amber); fill-opacity: .13; stroke: none; }

/* fill-opacity, not opacity: the reduced-motion block below forces opacity:1 on every
   [data-anim], which would paint this a solid amber slab. */
.sc-gap { fill: var(--sc-amber); fill-opacity: .16; }

/* ---- confidence states ----
   Three states, one path: the band scales about its own centre line. The scale has to
   sit on a DIFFERENT element from the one carrying scBandIn, that animation's `both`
   fill-mode pins transform at its end value, and the state would never show. */
.sc-band-w {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .45s cubic-bezier(.2, .8, .2, 1);
}

.sc-step[data-state="conf-85"] .sc-band-w { transform: scaleY(1.5); }
.sc-step[data-state="conf-95"] .sc-band-w { transform: scaleY(2.2); }

/* ---- the inline option chips ----
   A picker that has to share one row with its label, because a pane with a chart in it
   has a one-row budget at tier 1. walkthrough-card.js treats .sc-opt as a pick target
   alongside .sc-row. */
.sc-opts { display: flex; align-items: stretch; align-self: stretch; gap: 5px; flex: none; padding: 4px 0; }

.sc-opt {
  flex: none;
  padding: 0 7px;
  border-radius: 5px;
  border: 1px solid var(--sc-border-strong);
  background: none;
  color: var(--sc-muted);
  font-family: var(--sc-mono);
  font-size: var(--sc-val);
  line-height: 1;
  cursor: pointer;
}

.sc-opt:hover { color: var(--sc-text-3); }
.sc-opt.sel { border-color: var(--sc-amber); background: rgba(245, 166, 35, .14); color: var(--sc-amber); }

/* ---- selectable rows and inline action rows ---- */
button.sc-row { font-family: var(--sc-mono); cursor: pointer; }
button.sc-row:hover { border-color: var(--sc-border-strong); }
.sc-row.sel { border-color: var(--sc-amber); background: rgba(245, 166, 35, .12); }
.sc-row.sel .sc-k { color: var(--sc-amber); }
.sc-row.sc-done { border-color: rgba(46, 204, 113, .4); }
.sc-row.sc-done .sc-v { color: var(--sc-ok); }

.sc-act {
  flex: none;
  font-family: var(--sc-mono);
  font-size: var(--sc-val);
  color: var(--sc-amber);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
}

.sc-act:hover { color: var(--sc-amber-hover); }

/* ---- full-width commit button (steps 4 and 5) ----
   State classes are namespaced (.sc-done, not .done) because ad-landing.css is
   loaded alongside this one: its `.done { display: none }` on the booking panel
   silently swallowed this button once, and a colour-only override didn't win it
   back. Don't un-namespace them. */
.sc-cta {
  height: var(--sc-btn);
  flex: none;
  border: 0;
  border-radius: 8px;
  background: var(--sc-amber);
  color: var(--sc-bg);
  font-family: var(--sc-grotesk);
  font-size: var(--sc-val);
  font-weight: 700;
  letter-spacing: .02em;
  cursor: pointer;
}

.sc-cta:hover { background: var(--sc-amber-hover); }
.sc-cta.sc-done { background: rgba(46, 204, 113, .16); color: var(--sc-ok); box-shadow: inset 0 0 0 1px rgba(46, 204, 113, .4); }

/* ---- footer: step bars + counter ---- */
.sc-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: none;
  font-family: var(--sc-mono);
  font-size: var(--sc-label);
  letter-spacing: 1.5px;
  color: var(--sc-muted-3);
  white-space: nowrap;
}

.sc-bars { display: flex; gap: 5px; }

/* 16x3 visually. The padding + equal negative margin grows the hit area to 44px
   without adding a pixel of layout height, the spec drew these 3px tall and
   clickable, which its own tap-target rule forbids. */
.sc-bars button {
  width: 16px;
  height: 3px;
  padding: 20px 0;
  margin: -20px 0;
  border: 0;
  background: none;
  cursor: pointer;
  box-sizing: content-box;
}

.sc-bars button::before {
  content: '';
  display: block;
  height: 3px;
  border-radius: 2px;
  background: var(--sc-border-strong);
}

.sc-bars button[aria-current="step"]::before { background: var(--sc-amber); }
.sc-count b { color: var(--sc-text-3); font-weight: 400; }

/* ---- rows the narrow tiers can't afford ---- */
.sc:not([data-w="wide"]) [data-wide] { display: none; }

/* ---- beats ---- */
@keyframes scPulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@keyframes scRowIn { from { opacity: .15; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes scGrowW { from { width: 0; } to { width: 100%; } }
@keyframes scBandIn { from { opacity: 0; transform: scaleY(.15); } to { opacity: 1; transform: none; } }
/* A left-to-right wipe, not stroke-dashoffset: the forecast line's stroke-dasharray is
   its dash PATTERN, so the draw-on can't also live there. One rule covers both lines. */
@keyframes scWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes scArea { 0%, 100% { fill-opacity: .10; } 50% { fill-opacity: .26; } }

.sc [data-anim="row"] { animation: scRowIn .4s ease both; }
.sc [data-anim="chain"] { animation: scGrowW .9s ease both; }
.sc [data-anim="band"] { transform-box: fill-box; transform-origin: center; animation: scBandIn .55s ease both; }
.sc [data-anim="draw"] { animation: scWipe .9s .3s ease both; }
.sc [data-anim="area"] { animation: scArea 2.2s ease-in-out infinite; }

/* No element uses opacity:0 as a base state, and no chart uses a clipped clip-path or
   a full stroke-dashoffset as one either, so killing the animation can never leave a
   pane blank. It just lands in its end state, which is the point: a visitor who tabs
   straight in sees a drawn chart, not an empty box. */
@media (prefers-reduced-motion: reduce) {
  .sc [data-anim], .sc-actor i {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* only the chain line animates its width; `width:auto` on the actor dot would
     collapse it to nothing, which is what the unscoped version of this did. */
  .sc [data-anim="chain"] { width: auto; }
  /* Swiping still WORKS under reduced motion, it's navigation, not decoration. The
     pane just doesn't track the finger on the way there (the JS skips the transform). */
  .sc-step { transition: none; }
}
