/* ═══════════════════════════════════════════════════════════════════════════
   THE CIBIL FILM — stage and scenes
   Everything inside a scene is drawn off --p (0 to 1 as you scroll through
   it), so the drawing is scrubbed by the scroll rather than played on a
   timer. Scroll back and it runs backwards, which is the whole difference
   between a scroll effect and an animation that happens to be triggered.
   ═══════════════════════════════════════════════════════════════════════════ */

#cibil-film{
  --cf-ink:#E8F5EE; --cf-dim:#8FB3A1; --cf-mid:#1FA463; --cf-bright:#5FD9A0;
  --cf-late:#E0A030; --cf-bad:var(--cost-red-bar-on-dark, #E54B3E); --cf-paper:#F3F8F5;
  position:relative;display:block;margin:0 0 30px;
}

/* ── the pin ──────────────────────────────────────────────────────────────
   Two numbers decide how this feels, and both were too big.

   The TRACK was 520vh — five and a bit full screens of scrolling to get
   through five scenes. That is roughly a hundred vh per scene, which reads
   as the page having stopped responding. 300vh gives each scene about 60vh,
   which is one unhurried flick. The script derives progress from the track's
   own height (-rect.top / (height - vh)), so shortening it changes the pace
   and nothing else — no scene timing to re-tune.

   The STAGE was a full-bleed 100vh of dark green. Pinned, that meant the
   entire screen was green for the whole sequence, with green above it and
   green below it and no edge anywhere to tell you the page had not simply
   become green. It is a panel now: inset from the top, short of the full
   height, with the page visible around it. Same film, far less of it. */
#cibil-film.cf-on .cf-track{min-height:300vh;}
#cibil-film.cf-on .cf-stage{
  position:sticky;top:6vh;
  height:min(76vh,600px);
  width:min(1080px,94vw);margin:0 auto;
  display:grid;place-items:center;overflow:hidden;
  background:radial-gradient(130% 100% at 50% -10%,#10402F 0%,#0A2E25 55%,#07211B 100%);
  border-radius:22px;
  box-shadow:0 20px 60px rgba(6,24,18,.28);
}

/* ── why this block exists ─────────────────────────────────────────────
   position:sticky is defeated by ANY ancestor whose overflow is not
   visible, even when that ancestor never actually scrolls. Two here do:

     body.app-mode          overflow-x:hidden  overflow-y:auto
     #tab-container         overflow-x:hidden  overflow-y:auto

   Neither scrolls — both are as tall as their content, and the real
   scroller is <html>. But the stage still binds to the nearest of them,
   so it pinned inside a box that never moves and simply slid off the
   top with the page. Measured: the stage sat at top:-5619px at full
   scroll, and the film rendered as blank space.

   overflow:clip is the fix rather than overflow:visible. clip keeps the
   horizontal clipping those rules were added for, but does NOT create a
   scroll container, so sticky survives. Setting them to visible instead
   would restore pinning and hand the whole site a horizontal scrollbar.

   Scoped to html.cf-pin, which cibil-film.js only adds when the film is
   actually running, so nothing changes for a reduced-motion reader or a
   browser without the film. */
/* style.css:5397 declares, at max-width:768px:
     html, body, body.app-mode { overflow-x:hidden !important;
                                 overflow-y:visible !important; }
   and that is the one that has to be answered. Per spec, when one axis
   is hidden the other cannot stay visible — it computes to auto. So
   that rule, whose whole purpose was to let BODY scroll on iOS, is
   also what turns body into a scroll container and kills every sticky
   element inside the app shell.

   clip does not have that side effect: overflow-x:clip leaves
   overflow-y:visible genuinely visible. Same horizontal guard, no
   scroll container. !important is needed to answer !important, and
   body.app-mode is matched explicitly so the specificity beats theirs
   rather than relying on load order. */
html.cf-pin body,
html.cf-pin body.app-mode{overflow-x:clip !important;overflow-y:visible !important;}
html.cf-pin #tab-container{overflow-x:clip;overflow-y:visible;}
/* Older engines that do not know `clip` keep their old behaviour rather
   than losing the horizontal guard; the film degrades, the layout does
   not break. */
/* NO fallback here on purpose. The obvious one — overflow-x:hidden with
   overflow-y:visible — is the very combination that breaks sticky: per
   spec, hidden on one axis forces the other to compute to auto, so body
   becomes a scroll container again and the stage slides away. Writing
   that as the "fallback" reproduced the bug it was meant to avoid on
   every Safari below 16.
   Instead cibil-film.js checks for overflow:clip support and, when it
   is missing, does not pin at all — it renders the film as the static
   readable column. A story you can read beats a stage that cannot
   hold still. */
/* Too short to pin against: give it the story as a column instead of a
   stage that cannot move. */
/* ── a phone held sideways ────────────────────────────────────────────
   Too short to pin against, so the film becomes a column. It has to
   become a column COMPLETELY, which the first version of this block
   did not do: it unpinned the stage but left the scenes stacked at
   position:absolute and opacity:var(--o,0). With no scroll span the
   JS never writes --o, so every scene stayed at zero and the whole
   film rendered as a 326px box of nothing on any phone in landscape.

   --p is pinned to 1 as well, so each drawing sits at the END of its
   story rather than at frame zero — the house built, the umbrella
   open — instead of half-drawn shapes with no way to advance them. */
@media (max-height:560px){
  #cibil-film.cf-on .cf-track{min-height:0;}
  #cibil-film.cf-on .cf-stage{position:static;height:auto;padding:24px 0;}
  #cibil-film.cf-on .cf-inner{height:auto;display:block;}
  #cibil-film.cf-on .cf-scene{
    position:static;opacity:1;transform:none;pointer-events:auto;
    --p:1;margin:0 auto 26px;max-width:680px;
  }
  #cibil-film.cf-on .cf-scene:last-child{margin-bottom:0;}
  #cibil-film.cf-on .cf-rail{display:none;}
}

/* Has to fit INSIDE the stage now that the stage is no longer the whole
   screen — 100% of a 76vh panel, not 76vh of the viewport, or the art
   overflows the panel it is supposed to sit in. */
.cf-inner{
  position:relative;width:min(900px,90%);height:100%;
  display:grid;place-items:center;padding:18px 0;
}

/* ── scenes ───────────────────────────────────────────────────────────── */
.cf-scene{
  position:absolute;inset:0;display:grid;place-items:center;align-content:center;
  gap:clamp(14px,3vh,28px);grid-template-rows:auto auto;
  opacity:var(--o,0);
  transform:translateY(calc((1 - var(--o,0)) * 16px));
  pointer-events:none;
}
.cf-scene.is-live{pointer-events:auto;}
.cf-art{width:min(520px,78vw);height:auto;display:block;overflow:visible;}
.cf-copy{text-align:center;max-width:46ch;padding:0 16px;}
.cf-step{
  font-size:10.5px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;
  color:var(--cf-bright);margin:0 0 6px;
}
.cf-h{margin:0 0 7px;font-size:clamp(20px,3.4vw,31px);line-height:1.15;
  color:var(--cf-ink);font-weight:800;letter-spacing:-.01em;text-wrap:balance;}
.cf-p{margin:0;font-size:clamp(12.5px,1.7vw,15px);line-height:1.6;color:var(--cf-dim);}

/* ── progress rail ────────────────────────────────────────────────────── */
.cf-rail{position:absolute;left:50%;transform:translateX(-50%);bottom:18px;
  display:flex;gap:7px;z-index:3;}
.cf-dot{width:26px;height:3px;border-radius:2px;background:rgba(232,245,238,.18);
  transition:background .3s ease;}
.cf-dot.is-on{background:var(--cf-bright);}

/* ── shared drawing ───────────────────────────────────────────────────── */
.cf-art [stroke]{vector-effect:non-scaling-stroke;}
.cf-paper{fill:var(--cf-paper);opacity:.96;}
.cf-rule{stroke:#9DB8AA;stroke-width:3;stroke-linecap:round;}

/* 1 ─ the report arrives ─────────────────────────────────────────────────
   The art used to start at opacity 0 and 150px off to the left, so the
   first fifth of this scene was an empty panel with a line of text at the
   bottom — the viewer's first sight of the whole film, and it read as
   something failing to load rather than something about to move.

   It starts visible now and sharpens as you scroll: 0.34 at rest, full by
   22% through, and sliding 70px rather than 150. The movement is still
   there; what has gone is the blank. */
.cf-1 .cf-doc{
  transform:translateX(calc((1 - min(var(--p),.35) / .35) * -70px))
            rotate(calc((1 - min(var(--p),.35) / .35) * -4deg));
  opacity:calc(.34 + .66 * min(var(--p),.22) / .22);
}
.cf-1 .cf-rule{
  stroke-dasharray:120;
  stroke-dashoffset:calc(120 - 120 * clamp((var(--p) - .3) / .5, 0, 1));
}
.cf-1 .cf-stamp{
  opacity:clamp((var(--p) - .72) / .2, 0, 1);
  transform:scale(calc(.7 + .3 * clamp((var(--p) - .72) / .2, 0, 1))) rotate(-8deg);
  transform-origin:center;transform-box:fill-box;
}

/* 2 ─ every line is read ─────────────────────────────────────────────── */
.cf-2 .cf-scanbar{
  opacity:clamp(var(--p) / .12, 0, 1);
  transform:translateY(calc(var(--p) * 112px));
}
.cf-2 .cf-chip{
  transform:translateX(calc(var(--sx, 0px) * clamp((var(--p) - var(--d,0)) / .3, 0, 1)));
  opacity:calc(.25 + .75 * clamp((var(--p) - var(--d,0)) / .3, 0, 1));
}
.cf-2 .cf-lanelab{opacity:clamp((var(--p) - .62) / .25, 0, 1);}
.cf-clean{fill:var(--cf-mid);}
.cf-late{fill:var(--cf-late);}
.cf-bad{fill:var(--cf-bad);}

/* 3 ─ the EMIs become one number ─────────────────────────────────────── */
.cf-3 .cf-bar{
  transform:scaleY(clamp((var(--p) - var(--d,0)) / .34, 0, 1));
  transform-origin:bottom;transform-box:fill-box;
}
.cf-3 .cf-sum{
  opacity:clamp((var(--p) - .62) / .22, 0, 1);
  transform:translateY(calc((1 - clamp((var(--p) - .62) / .22, 0, 1)) * 10px));
}

/* 4 ─ the ceiling ────────────────────────────────────────────────────── */
.cf-4 .cf-cap{
  stroke-dasharray:260;
  stroke-dashoffset:calc(260 - 260 * clamp(var(--p) / .34, 0, 1));
}
.cf-4 .cf-used{transform:scaleX(clamp((var(--p) - .26) / .36, 0, 1));transform-origin:left;transform-box:fill-box;}
.cf-4 .cf-free{transform:scaleX(clamp((var(--p) - .56) / .32, 0, 1));transform-origin:left;transform-box:fill-box;}
.cf-4 .cf-freelab{opacity:clamp((var(--p) - .74) / .2, 0, 1);}

/* 5 ─ the score and the dashboard ────────────────────────────────────── */
.cf-5 .cf-arc{
  stroke-dasharray:189;
  stroke-dashoffset:calc(189 - 189 * clamp(var(--p) / .52, 0, 1));
}
.cf-5 .cf-needle{
  transform:rotate(calc(-90deg + 180deg * clamp(var(--p) / .52, 0, 1)));
  transform-origin:center;transform-box:fill-box;
}
.cf-5 .cf-tile{
  opacity:clamp((var(--p) - var(--d,0)) / .18, 0, 1);
  transform:translateY(calc((1 - clamp((var(--p) - var(--d,0)) / .18, 0, 1)) * 12px));
}
.cf-scoretext{fill:var(--cf-bright);font-weight:800;font-size:28px;
  font-variant-numeric:tabular-nums;}
.cf-tilefill{fill:rgba(232,245,238,.09);stroke:rgba(95,217,160,.3);stroke-width:1.5;}

/* ── the reduced-motion reading ───────────────────────────────────────── */
#cibil-film.cf-static .cf-stage{
  position:static;height:auto;padding:24px 0;border-radius:18px;
}
#cibil-film.cf-static .cf-inner{height:auto;display:block;}
#cibil-film.cf-static .cf-scene{
  position:static;opacity:1;transform:none;margin:0 auto 30px;max-width:680px;
}
#cibil-film.cf-static .cf-rail{display:none;}

/* ═══════════════════════════════════════════════════════════════════════
   "What this actually means" — the discussion above the alerts
   ───────────────────────────────────────────────────────────────────────
   Set as prose, not as cards. It is meant to be read start to finish, and
   chopping it into tiles would turn an argument back into a list of facts.
   ═══════════════════════════════════════════════════════════════════════ */
.cd-block{
  background:var(--card-bg,#fff);border:1px solid var(--border-glass);
  border-radius:16px;padding:20px 22px;margin:0 0 18px;
}
.cd-wrap{max-width:66ch;}
.cd-eyebrow{
  margin:0 0 8px;font-size:10.5px;font-weight:800;letter-spacing:1.1px;
  text-transform:uppercase;color:var(--text-muted,#8a9a92);
}
.cd-h{margin:0 0 10px;font-size:19px;font-weight:800;letter-spacing:-.3px;line-height:1.3;}
.cd-p{margin:0 0 12px;font-size:14.5px;line-height:1.65;}
.cd-p b{font-weight:800;}
.cd-pull{
  margin:14px 0;padding:2px 0 2px 14px;font-size:15px;line-height:1.55;
  border-left:3px solid var(--brand-green,#18C979);
}
.cd-pull.is-warn{border-left-color:#E3B341;}
.cd-pull.is-bad{border-left-color:var(--cost-red-auto,#B3261E);}
.cd-sub{margin:20px 0 8px;font-size:14px;font-weight:800;}
.cd-acts{margin:0;padding-left:20px;}
.cd-acts li{margin:0 0 7px;font-size:14px;line-height:1.6;}
.cd-acts b{font-weight:800;}
.cd-fine{
  margin:16px 0 0;font-size:12px;line-height:1.6;color:var(--text-muted,#8a9a92);
}

/* ── the four credit-report panels ────────────────────────────────────────
   Score arc, the five factors, utilisation against the 30% line, and the
   three figures to check before trusting any of it. All four draw numbers
   that were already parsed — the prototype drew them and the live screen
   did not. */
/* ══ THE --cd-* TOKENS, WHICH NOTHING HAS EVER DEFINED ═══════════════
   Every rule below reaches for var(--cd-card, var(--card, #fff)) and
   neither --cd-card nor --card is declared anywhere in this project, so
   all of them have always resolved to the hardcoded #fff at the end.

   In light mode that was invisible as a bug: white panels on a white
   page. In DARK mode the panel stayed #fff while the text inherited the
   dark theme's light ink — white on white, measured at 1.0:1. The
   heading of every factor panel on the CIBIL desk was unreadable, and
   nothing errored.

   Declared here, both themes, scoped to the panels themselves so they
   work wherever they are mounted. Same shape as the #crm-host token
   block in crm.css, and for the same reason: a detached panel that does
   not carry its own tokens inherits a fallback nobody chose. */
.cp-block, .cd-block {
  --cd-card:  #FFFFFF;
  --cd-line:  #E3EDE7;
  --cd-muted: #5A6B62;
  --cd-ok:    #147A47;
}
[data-theme="dark"] .cp-block,
[data-theme="dark"] .cd-block {
  --cd-card:  #0B1A14;
  --cd-line:  #28473A;
  --cd-muted: #9FB8AB;
  --cd-ok:    #3FBF80;
}

.cp-block {
  background: var(--cd-card, var(--card, #fff));
  border: 1px solid var(--cd-line, var(--line, #e5e7eb));
  border-radius: .7rem; padding: 18px 20px; margin: 0 0 14px;
}
.cp-eyebrow {
  margin: 0 0 .3rem; font-size: .7rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--cd-muted, #6b7280);
}
.cp-block h4 { margin: 0 0 .3rem; font-size: 1.05rem; }
.cp-sub, .cp-foot { font-size: .82rem; line-height: 1.55; color: var(--cd-muted, #6b7280); }
.cp-sub { margin: 0 0 .9rem; }
.cp-foot { margin: .9rem 0 0; }

/* 1 — the arc */
.cp-arcrow { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.cp-gauge { width: 150px; height: 132px; flex: 0 0 auto; }
.cp-gauge .cp-track { fill: none; stroke: var(--cd-line, #e5e7eb); stroke-width: 9; stroke-linecap: round; }
.cp-gauge .cp-fill  { fill: none; stroke: var(--cd-ok, #15803d); stroke-width: 9; stroke-linecap: round; }
.cp-gauge .cp-score { font-size: 25px; font-weight: 800; text-anchor: middle; fill: currentColor; }
.cp-gauge .cp-band  { font-size: 8px; font-weight: 700; letter-spacing: .1em; text-anchor: middle; fill: var(--cd-ok, #15803d); }
.cp-gauge .cp-end   { font-size: 8px; fill: var(--cd-muted, #6b7280); }
.cp-arctext { flex: 1 1 260px; font-size: .9rem; line-height: 1.6; }

/* 2 — five factors */
.cp-factors { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.cp-factor { border: 1px solid var(--cd-line, #e5e7eb); border-radius: .5rem; padding: 10px 12px; }
.cp-fhead { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.cp-fhead b { font-size: .85rem; }
.cp-fhead span { font-size: .72rem; color: var(--cd-muted, #6b7280); text-align: right; }
.cp-fbar { height: 3px; border-radius: 2px; background: var(--cd-line, #e5e7eb); margin: .45rem 0 .5rem; }
.cp-fbar i { display: block; height: 100%; border-radius: 2px; background: var(--cd-ok, #15803d); }
.cp-factor.is-bad .cp-fbar i { background: var(--cd-bad, #b91c1c); }
.cp-factor.is-bad .cp-fhead b { color: var(--cd-bad, #b91c1c); }
.cp-factor p { margin: 0; font-size: .78rem; line-height: 1.5; color: var(--cd-muted, #6b7280); }

/* 3 — utilisation */
.cp-utils { display: flex; flex-direction: column; gap: 10px; }
.cp-util { display: grid; grid-template-columns: 140px 1fr 150px; gap: 12px; align-items: center; }
.cp-uname b { display: block; font-size: .85rem; }
.cp-uname span { font-size: .72rem; color: var(--cd-muted, #6b7280); }
.cp-ubar { position: relative; height: 9px; border-radius: 5px; background: var(--cd-line, #e5e7eb); }
.cp-ubar i { display: block; height: 100%; border-radius: 5px; background: var(--cd-ok, #15803d); }
.cp-ubar.is-over i { background: var(--cd-bad, #b91c1c); }
/* the 30% line itself */
.cp-ubar::after {
  content: ''; position: absolute; left: 30%; top: -3px; bottom: -3px;
  width: 1px; background: var(--cd-muted, #6b7280); opacity: .55;
}
.cp-ubar.is-unknown { opacity: .45; }
.cp-unum { text-align: right; }
.cp-unum b { display: block; font-size: .9rem; font-variant-numeric: tabular-nums; }
.cp-unum span { font-size: .72rem; color: var(--cd-muted, #6b7280); }

/* 4 — before you act */
.cp-verify { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.cp-v { border: 1px solid var(--cd-line, #e5e7eb); border-radius: .5rem; padding: 10px 12px; }
.cp-v span { font-size: .74rem; color: var(--cd-muted, #6b7280); }
.cp-v b { display: block; font-size: 1.15rem; margin: .15rem 0 .3rem; font-variant-numeric: tabular-nums; }
.cp-v p { margin: 0; font-size: .75rem; line-height: 1.5; color: var(--cd-muted, #6b7280); }

@media (max-width: 640px) {
  .cp-util { grid-template-columns: 1fr; gap: 4px; }
  .cp-unum { text-align: left; }
}
