/* PUBLIC WEBSITE — design file for this surface ONLY.
 *
 * Deliberately NOT shared with the other surfaces. The owner's call: each of
 * the four (public website, course portal, client dashboard, admin console)
 * owns its own design file, so a change made for one can never reach into
 * another and break it.
 *
 * The trade-off is stated rather than hidden: four files carrying similar
 * intent WILL drift unless changed together. When a rule below is edited for
 * brand reasons rather than for something specific to this surface, the same
 * edit probably belongs in the other three.
 *
 * Tokens fall back to literals, so this file renders correctly on its own and
 * inherits the measured palette (including dark mode) where one is present.
 */

/* ── The lede ─────────────────────────────────────────────────────────────
   The reference opens with a SENTENCE, not a number: it says what happened and
   leaves the figures below as the evidence. A page of numbers alone makes the
   reader do the interpreting every time. */
.lede {
  font: 400 16.5px/1.6 var(--sans, 'IBM Plex Sans', system-ui, sans-serif);
  color: var(--dim, #5B6679);
  margin: 2px 0 16px;
  max-width: 74ch;
}
.lede b { color: var(--txt, #0B1220); font-weight: 600; }

/* ── Labels as furniture ──────────────────────────────────────────────────
   Small, heavy, tracked wide. They stop competing with the data they
   introduce, which is what lets the data sit forward. */
.ph { letter-spacing: .14em; font-size: 10px; }
.ph .x { letter-spacing: 0; }

/* ── The bordered stat grid ───────────────────────────────────────────────
   One rounded container divided by hairlines, not cards floating in space, so
   a row of figures reads as a single instrument rather than scattered parts. */
.sgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 0; border: 1px solid var(--line, #E3E8EF);
  border-radius: var(--r-panel, 12px);
  background: var(--panel, #FFFFFF);
  overflow: hidden; margin: 12px 0;
}
.sgrid > .stat {
  padding: 16px 18px 17px; display: flex; flex-direction: column; gap: 5px;
  min-height: 104px;
  border-right: 1px solid var(--line, #E3E8EF);
  border-bottom: 1px solid var(--line, #E3E8EF);
}
.sgrid > .stat:last-child { border-right: 0; }
.sgrid .stat-l {
  font: 600 9.5px var(--sans, 'IBM Plex Sans', system-ui, sans-serif);
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint, #616A77);
}
.sgrid .stat-v {
  font: 600 27px/1.05 var(--mono, 'IBM Plex Mono', ui-monospace, monospace);
  letter-spacing: -.04em; color: var(--txt, #0B1220);
  font-variant-numeric: tabular-nums;
}
.sgrid .stat-s {
  font: 400 12px var(--sans, 'IBM Plex Sans', system-ui, sans-serif);
  color: var(--dim, #5B6679); margin-top: auto;
}

@media (max-width: 640px) {
  .lede { font-size: 15px; margin-bottom: 12px; }
  .sgrid > .stat { padding: 13px 14px; min-height: 88px; }
  .sgrid .stat-v { font-size: 23px; }
}


/* ── The contact form ──────────────────────────────────────────────────────
   The page already had a well-built contact form; what it lacked was somewhere
   to send the enquiry. It posted a mailto: instead, which assumes the visitor
   has a mail client configured, loses the message entirely if they do not, and
   leaves no record anywhere - and a Research Analyst must keep a record of
   client communications. Only the two pieces the form was missing are styled
   here; the rest of its appearance is its own. */

/* Off-screen rather than display:none - a bot reads the DOM, and some skip
   fields that are explicitly hidden. */
.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.cform-note { margin: 12px 0 0; font-size: 14px; min-height: 1.2em; }
.cform-note.ok  { color: var(--bull, #047857); font-weight: 600; }
.cform-note.bad { color: var(--bear, #C81E1E); font-weight: 600; }


/* ── Floating rail: WhatsApp, jump menu, back to top ──────────────────────
   This page runs to roughly 22,000 pixels. The top navigation scrolls away with
   it, so from a third of the way down there is no way to reach the investor
   charter, the complaint data or the contact form — nor to get back up —
   without a long manual scroll.

   Four floating controls now share one corner, so they are laid out as a rail
   rather than positioned one at a time. Doing it individually is what produced
   the earlier overlap: each new button was placed against an assumption about
   where the others were.

   The accessibility toolbar is the fixed point, and its geometry CHANGES with
   width — it lifts itself on small screens to clear the client dashboard's
   bottom tab bar:

     desktop   fab right:18 bottom:18 (56px, occupying 18-74)
               its panel opens at bottom:84
     <=820px   fab right:14 bottom:74 +safe-area (occupying 74-130)
               its panel opens at bottom:140

   So the rail is a COLUMN beside it on a desktop (the corner floor is taken,
   and bottom:84 belongs to its panel), and a ROW along the bottom on a phone
   (where the toolbar has vacated the floor by lifting to 74px). The breakpoint
   is the toolbar's own 820px, not one chosen independently: two components
   sharing a corner must change shape at the same width, or they overlap
   between the two thresholds. */
.frail {
  position: fixed; right: 86px; bottom: 18px; z-index: 2147483002;
  display: flex; flex-direction: column-reverse; gap: 10px; align-items: flex-end;
}
.frail[hidden] { display: none; }

.frail-btn {
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid rgba(8, 12, 20, .10);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; text-decoration: none; padding: 0;
  box-shadow: 0 6px 20px -6px rgba(8, 12, 20, .45);
  background: var(--white, #fff); color: var(--text-dom, #0B1220);
}
.frail-btn svg { width: 21px; height: 21px; }
.frail-btn:hover { border-color: rgba(8, 12, 20, .22); }
.frail-jump { background: var(--blue, #2563EB); color: #fff; }
.frail-jump:hover { background: var(--blue-hover, #1D4ED8); }
/* WhatsApp's own brand green. Kept because a WhatsApp button that is not green
   is not recognised as one, which is the entire point of putting it here. */
.frail-wa { background: #25D366; color: #fff; border-color: #1DA851; }
.frail-wa:hover { background: #1DA851; }
.frail-top { font: 600 11px var(--sans, 'IBM Plex Sans', system-ui, sans-serif); }

/* The jump menu hangs off its own button. */
.frail-jumpwrap { position: relative; }
.secnav-panel {
  position: absolute; right: 0; bottom: 56px;
  width: min(260px, calc(100vw - 36px));
  background: var(--white, #fff); border: 1px solid var(--line, #E3E8EF);
  border-radius: 12px; overflow: hidden;
  box-shadow: 0 18px 44px -12px rgba(8, 12, 20, .34);
  max-height: min(60vh, 420px); overflow-y: auto;
}
.secnav-panel[hidden] { display: none; }
.secnav-panel .secnav-t {
  margin: 0; padding: 11px 14px 9px;
  font: 600 10px var(--sans, 'IBM Plex Sans', system-ui, sans-serif);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-sec, #5B6679);
  border-bottom: 1px solid var(--line, #E3E8EF);
}
.secnav-panel a {
  display: block; padding: 10px 14px; font-size: 14.5px;
  color: var(--text-dom, #0B1220); text-decoration: none;
  border-bottom: 1px solid var(--line, #E3E8EF);
}
.secnav-panel a:last-child { border-bottom: 0; }
.secnav-panel a:hover, .secnav-panel a:focus { background: var(--surface, #EEF2F7); outline: none; }
.secnav-panel a[aria-current="true"] { color: var(--blue, #2563EB); font-weight: 600; }

/* On a phone the toolbar has lifted to 74px, so the floor is free: the rail
   lies along it as a row instead of stacking into the toolbar. */
@media (max-width: 820px) {
  .frail {
    right: 14px; bottom: calc(14px + env(safe-area-inset-bottom));
    flex-direction: row; align-items: center;
  }
  .frail-btn { width: 44px; height: 44px; }
}
@media print { .frail { display: none; } }


/* ── Micro-motion ──────────────────────────────────────────────────────────
   Small, functional movement only: each one answers "did that register?" or
   "where am I?" — not decoration. On a SEBI RA's site, motion that draws the
   eye away from a figure or a disclosure is a cost, not a feature.

   Three rules this file keeps:

   1. Nothing here EVER hides content. The page's existing .reveal system is
      opacity:1 by default and only hides under html.js, which is what stops a
      failed script leaving a disclosure invisible. Everything below animates
      transform, colour or a pseudo-element — never the visibility of text.
   2. Everything is transform/opacity, so it runs on the compositor and cannot
      cause layout thrash on a phone.
   3. prefers-reduced-motion is already handled globally by index.html, which
      collapses every animation and transition to 0.001ms. These rules inherit
      that, and the few that need an explicit off-switch get one below.
*/

/* Primary actions acknowledge a press. A button that looks identical before
   and after a tap is the commonest reason someone taps it twice. */
.btn-primary, .btn-secondary, .cform-btn, .frail-btn {
  transition: transform .12s cubic-bezier(.4, 0, .2, 1),
              box-shadow .18s cubic-bezier(.4, 0, .2, 1),
              background-color .18s ease, border-color .18s ease;
}
.btn-primary:hover, .btn-secondary:hover, .cform-btn:hover { transform: translateY(-1px); }
.btn-primary:active, .btn-secondary:active, .cform-btn:active,
.frail-btn:active { transform: translateY(0) scale(.97); }

/* Arrows lean in the direction they promise to take you. */
.btn-primary .arrow, .btn-secondary .arrow { display: inline-block; transition: transform .16s ease; }
.btn-primary:hover .arrow, .btn-secondary:hover .arrow { transform: translateX(3px); }

/* Cards lift a little, so a grid of them reads as touchable rather than as a
   printed table. 1px and a softer shadow — enough to notice, not enough to
   distract from the figures on them. */
.card-feature, .step-card {
  transition: transform .2s cubic-bezier(.4, 0, .2, 1), box-shadow .2s ease;
}
.card-feature:hover, .step-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -14px rgba(8, 12, 20, .28);
}

/* The nav underline and the "Years in markets" counter are NOT here: the page
   already implements both (index.html). A second definition of one behaviour is
   how two rules end up disagreeing after someone edits only one of them. */

/* The floating rail arrives rather than appearing, and each button lands a beat
   after the one before it. It is the only thing on the page that appears
   mid-scroll, so an abrupt pop reads as a glitch. */
.frail-btn { animation: frail-in .28s cubic-bezier(.2, .8, .3, 1) backwards; }
.frail-btn:nth-child(2) { animation-delay: .05s; }
.frail-btn:nth-child(3) { animation-delay: .1s; }
.frail-jumpwrap .frail-btn { animation-delay: .05s; }
@keyframes frail-in {
  from { opacity: 0; transform: translateY(8px) scale(.9); }
  to   { opacity: 1; transform: none; }
}

/* The jump menu opens from the button it belongs to. */
.secnav-panel { transform-origin: bottom right; animation: panel-in .16s cubic-bezier(.2, .8, .3, 1); }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(6px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* The status dot on "SEBI Registered" breathes very slowly. Slow enough to read
   as alive rather than as an alert — an urgent pulse next to a registration
   number would be the wrong signal entirely. */
.live-dot { animation: live-breathe 3.2s ease-in-out infinite; }
@keyframes live-breathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .55; transform: scale(.9); }
}

@media (prefers-reduced-motion: reduce) {
  .btn-primary:hover, .btn-secondary:hover, .cform-btn:hover,
  .card-feature:hover, .step-card:hover { transform: none; }
  .frail-btn, .secnav-panel, .live-dot { animation: none; }
}

/* The plan card's two calls to action.
   They used to sit loose in the text flow as two inline-flex anchors with a
   margin between them. Inline-flex boxes align on the TEXT BASELINE, and an
   inline-flex box's baseline is that of its first line — so the arrow glyph in
   "Subscribe" was enough to push the pair out of line despite both being
   exactly 44px tall. A flex row aligns by box rather than by baseline.

   align-items:stretch so the two stay the same height if either ever wraps to
   a second line, and wrap so a narrow card stacks them instead of overflowing. */
.plan-cta {
  display: flex; flex-wrap: wrap; align-items: stretch;
  gap: 10px;
  /* The pair now sits OUTSIDE the card body, as the card's last child, so it
     carries its own padding — the body's 32px no longer wraps it. */
  padding: 0 32px 28px;
  /* No margin-top:auto here any more. Alignment now comes from the CARD being a
     flex column whose BODY takes flex:1 — the buttons are the last child, so
     they land on the card's floor. Pinning to the body's floor instead only
     worked while every card's features block was the same height, which is
     exactly how the Long Term card ended up 23px out. */
  margin-top: 0;
}
/* The two share the row EQUALLY rather than each demanding its natural width.
   At the site's own button padding they measure 140px and 142px, which needs
   292px — two more than a 340px plan card actually offers once its padding is
   taken off. So they wrapped, and a wrapped pair reads as misaligned. Equal
   flex basis with min-width:0 lets them size to whatever the card has, and the
   slightly tighter horizontal padding here buys the room back for the label. */
.plan-cta .btn-primary, .plan-cta .btn-secondary {
  margin: 0; flex: 1 1 0; min-width: 0; padding: 0 14px; white-space: nowrap;
}
/* Below this the pair genuinely cannot sit side by side legibly, so stacking
   full width is the honest answer rather than two cramped pills. */
@media (max-width: 380px) {
  .plan-cta { flex-direction: column; }
  .plan-cta .btn-primary, .plan-cta .btn-secondary { width: 100%; }
}

/* Drawn icons sitting INSIDE a small uppercase label.
   The base .mkt-glyph is 18px and forces --blue, which is right beside a 40px
   heading and wrong beside an 11px label in the step colours (#A34D00 amber,
   #B42318 red) — it would read as oversized and as belonging to a different
   element. Scoped down and set to inherit, so each icon takes the colour of
   the label it introduces. The draw animation, its reduced-motion handling and
   the 2.5s reveal failsafe all still come from the page's own rules. */
.card-feature .mkt-glyph,
.step-card .mkt-glyph {
  width: 13px; height: 13px; margin-right: 7px;
  vertical-align: -1px; color: inherit;
}
/* An FAQ question is a 17px heading, not an 11px label, so its icon is sized to
   that instead — and kept in the accent colour, since here it marks the
   question rather than colouring alongside a coloured label. */
.card-feature h3 .mkt-glyph {
  width: 16px; height: 16px; margin-right: 9px;
  vertical-align: -2px; color: var(--blue, #2563EB);
}
/* The plan heading is 28px; its icon leads the name at a matching weight.
   Listed at the FAQ rule's specificity too: `.card-feature h3 .mkt-glyph` is
   (0,2,1) and a bare `.plan-glyph` is (0,1,0), so inside a .card-feature the
   plan icon would silently shrink to the FAQ's 16px. */
.plan-glyph,
.card-feature h3 .plan-glyph {
  width: 22px; height: 22px; margin-right: 10px; vertical-align: -3px;
}

/* Long unbreakable strings must never widen the page.
   An email address is one word to a browser: dwipanjit.researchanalyst@gmail.com
   measures 303px and, indented in the contact block, reached 375px on a 360px
   screen — so the WHOLE PAGE scrolled sideways, on the section a visitor uses
   to make contact. Allowing a break inside the address costs nothing (it stays
   selectable and still opens the mail client) and removes the overflow.

   Applied to the addresses and URLs specifically rather than globally: a blanket
   break-anywhere would also break ordinary prose mid-word. */
a[href^="mailto:"],
a[href^="tel:"],
#contact a,
.footer-link {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ═══════════════════════════════════════════════════════════════════════════
   IN-PROSE LINKS CARRY AN UNDERLINE (WCAG 1.4.1 "Use of Colour")

   A link sitting inside a paragraph was distinguishable only by its blue —
   invisible to a reader with a colour-vision deficiency, and the one place it
   matters most here is the grievance card, where the SCORES, SmartODR and
   email links are the investor's escalation route.

   Scoped to links inside body copy on purpose. Navigation, buttons and cards
   are distinguishable by position, shape and background, so underlining them
   would add noise without adding information; the audit only flagged prose.
   The offset keeps the rule clear of descenders in IBM Plex Sans. */
p a:not([class*="btn"]):not(.badge),
li a:not([class*="btn"]):not(.badge) {
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE INFO DOT — ported from the consoles, which took it from MTF Analytics.

   This surface keeps its own design file, so the rule is written out here
   rather than shared. That is the owner's architecture: a change made for one
   surface can never reach into another.

   Only ONE of the four console components is ported. The hero-stat card and
   the segmented control have nothing on a marketing page to attach to, and a
   DELTA PILL would be worse than useless: nothing on a public page changes
   period to period, so a pill reading "▲" would be decoration imitating data.
   That is the habit this whole pass has been removing, and importing it here
   under the banner of a redesign would be the same mistake with better
   typography.

   What the dot IS for: a term a buyer must understand BEFORE paying. The fee
   is charged in advance and the plan is a contract, so "per month" and
   "half-yearly" carry consequences a prospect should not have to infer.
   ═════════════════════════════════════════════════════════════════════════ */
.info-dot{
  display:inline-flex;align-items:center;justify-content:center;
  width:15px;height:15px;border-radius:50%;
  border:1px solid var(--text-ter,#6b7280);color:var(--text-ter,#6b7280);
  background:none;padding:0;margin-left:6px;flex:0 0 auto;cursor:help;
  font:600 9.5px/1 var(--font-sans,'IBM Plex Sans',system-ui,sans-serif);
  letter-spacing:0;text-transform:none;vertical-align:middle;
}
.info-dot:hover,.info-dot:focus-visible{
  color:var(--text-dom,#0b1220);border-color:var(--text-dom,#0b1220);
}
.info-dot:focus-visible{outline:2px solid var(--blueText,#2563eb);outline-offset:2px}
/* A finger needs more than 15px. */
@media (pointer:coarse){.info-dot{width:22px;height:22px;font-size:12px}}

/* A counted figure, set so its thousands separator does not float.
   .fig is monospace, where a comma occupies a full character cell — at 24px
   "1,284" reads as "1 , 284", the same fault the plan prices had at 40px.
   Sans with tabular figures keeps the digits in their boxes (so a changing
   number does not jitter) and gives the comma its proper narrow width. */
.count-fig{
  font-family: var(--font-sans, 'IBM Plex Sans', system-ui, sans-serif);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ── OFFICIAL PROFILE LINKS ───────────────────────────────────────────────
   Rendered only for handles that are actually configured; see build-site.mjs.
   Sized for a finger and given a real focus ring, because these are the only
   outbound links in the footer that leave the site for a third party.
   rel="me" is set on each anchor: it is the microformat that lets a profile
   link back and be verified as belonging to this site, which is worth having
   when the page's headline warning is about impersonation. */
.social-row{display:flex;gap:10px;margin-top:18px;flex-wrap:wrap}
.social-link{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;border-radius:8px;
  border:1px solid rgba(255,255,255,0.18);color:rgba(255,255,255,0.72);
  background:rgba(255,255,255,0.04);transition:color .14s,border-color .14s,background .14s;
}
.social-link svg{width:17px;height:17px;fill:currentColor;display:block}
.social-link:hover{color:#fff;border-color:rgba(255,255,255,0.5);background:rgba(255,255,255,0.10)}
.social-link:focus-visible{outline:2px solid #7CB6F2;outline-offset:2px}
@media (pointer:coarse){.social-link{width:44px;height:44px}.social-link svg{width:20px;height:20px}}

/* ── THE TOP STRIP ────────────────────────────────────────────────────────
   A hairline rule between the fraud banner and the hero, carrying the
   official profiles and the live visit count.

   It sits directly above the analyst's name and registration number, so it is
   deliberately quiet: small, muted, one hairline, no fill. Anything with more
   weight would compete with the two things on this page that actually matter.
   On a phone it wraps to two rows and centres rather than shrinking further. */
.topstrip{
  border-bottom:1px solid var(--surface,#EDEDF2);
  background:var(--bg-alt,#FAFBFC);
}
.topstrip-in{
  max-width:1262px;margin:0 auto;padding:10px 20px;
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
}
.topstrip .social-row{margin-top:0}
/* On this ground the icons are outlines rather than the footer's light-on-dark
   treatment, so .social-link is re-stated here for the light strip. */
.topstrip .social-link{
  width:32px;height:32px;border-radius:8px;
  border:1px solid var(--surface,#EDEDF2);
  color:var(--text-ter,#6b7280);background:#fff;
}
.topstrip .social-link svg{width:16px;height:16px}
.topstrip .social-link:hover{
  color:var(--text-dom,#0b1220);border-color:var(--text-ter,#6b7280);background:#fff;
}
/* Not yet published: visible so the row reads as a set, plainly inert so it
   never looks like a link that is simply broken. */
.social-link.is-pending{
  opacity:.34;cursor:default;background:transparent;
}
.social-link.is-pending:hover{color:var(--text-ter,#6b7280);border-color:var(--surface,#EDEDF2)}

.topstrip-count{
  margin:0;font-size:12.5px;color:var(--text-ter,#6b7280);
  font-variant-numeric:tabular-nums;letter-spacing:.01em;
}
.topstrip-count b{color:var(--text-dom,#0b1220);font-weight:600}

@media (max-width:640px){
  .topstrip-in{justify-content:center;gap:10px;padding:9px 16px}
  .topstrip-count{width:100%;text-align:center}
}
@media (pointer:coarse){
  .topstrip .social-link{width:40px;height:40px}
  .topstrip .social-link svg{width:18px;height:18px}
}

/* ─── busy buttons & toasts (js/ui-busy.js) ──────────────────────────────────
   A press used to be silent: you found out it worked by noticing the page had
   redrawn. The spinner says "heard you", the toast says "done". Both are
   driven centrally, so no handler needs to opt in. */
button[aria-busy="true"], .act[aria-busy="true"], [role="button"][aria-busy="true"]{
  position:relative; opacity:.65; cursor:progress; pointer-events:none;
}
button[aria-busy="true"]::before, .act[aria-busy="true"]::before,
[role="button"][aria-busy="true"]::before{
  content:""; display:inline-block; width:.72em; height:.72em;
  margin-right:.5em; vertical-align:-.05em;
  border:2px solid currentColor; border-right-color:transparent;
  border-radius:50%; animation:ui-spin .6s linear infinite;
}
@keyframes ui-spin{to{transform:rotate(360deg)}}

.ui-toasts{position:fixed; right:16px; bottom:16px; z-index:9999;
  display:flex; flex-direction:column; gap:8px; pointer-events:none; max-width:min(92vw,380px)}
.ui-toast{background:#12321f; color:#eafaf1; border:1px solid #1f6f47;
  border-left:3px solid #2f9e63; border-radius:6px; padding:9px 13px;
  font-size:13px; line-height:1.45; box-shadow:0 6px 22px rgba(0,0,0,.28);
  animation:ui-toast-in .22s ease-out}
.ui-toast.is-bad{background:#331b19; color:#fbe9e7; border-color:#7d332b; border-left-color:#c4483a}
.ui-toast.is-out{opacity:0; transform:translateY(6px); transition:opacity .35s, transform .35s}
@keyframes ui-toast-in{from{opacity:0; transform:translateY(8px)}to{opacity:1; transform:none}}

@media (prefers-reduced-motion:reduce){
  button[aria-busy="true"]::before,.act[aria-busy="true"]::before,
  [role="button"][aria-busy="true"]::before{animation:ui-pulse 1.1s ease-in-out infinite}
  @keyframes ui-pulse{50%{opacity:.35}}
  .ui-toast{animation:none}
  .ui-toast.is-out{transition:opacity .2s}
}
