/* build: v15.0 — Tier 2 detail pages + Ganga Tattva. See docs/BUILD-v15.0.md */
/* ============================================================
   COMPONENT LIBRARY
   Every entry transcribed from visual-design-system-checklist.md
   Part A, A3. Component names below match the checklist's own
   names exactly, so the two can be read side by side.
   ============================================================ */


/* ------------------------------------------------------------
   Hero — two-paragraph felt-recognition        (Home, My Story)

   Opening line is a standard H1, same treatment as every other
   page's hero. Portrait sits side-by-side, stacking on mobile.
   ------------------------------------------------------------ */

.hero-felt__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.46fr);
  gap: var(--space-8);
  align-items: center;
}

.hero-felt__copy > * + * { margin-top: var(--space-5); }

.hero-felt__opening {
  max-width: 26ch;
}

.hero-felt__copy p {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  max-width: var(--measure);
}

/* Hero sub-line (Home, My Story). Was --size-h2 in the heading
   serif at 600 with max-width:none, directly beneath an H1 capped
   at 26ch. Same family, same weight, one step apart, and the
   smaller one ran wider: no hierarchy for the eye to step down
   through, just two blocks of serif bold where the lower one had
   more area. Now Lead in the body face, capped narrower than the
   headline above it. */
.hero-felt__copy p.hero-felt__lead {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  color: var(--charcoal);
  max-width: 48ch;
}

.hero-felt__copy p.hero-felt__lead--sm {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  max-width: 48ch;
}

/* Orientation line. Was .hero-felt__signoff, a bare "I'm Arvind
   Menon." with nothing to do. It now states what the practice
   actually is, which is the one thing the old hero never told a
   cold visitor. Weighted so it separates from the recognition
   line above it without competing with the H1. */
.hero-felt__orient {
  font-weight: var(--weight-semi);
  max-width: 44ch;
}

.hero-felt__cta { margin-top: var(--space-6); }

/* Supporting text beside a CTA button, not inside it (remediation
   5) — a time estimate belongs next to the action, not folded into
   the button's own accessible name. */
.cta-support {
  font-size: var(--size-caption);
  color: var(--linework);
  margin-top: var(--space-3);
}

/* Orientation line, program-page variant. Same job as
   .hero-felt__orient on Home and therefore the same treatment:
   the line that tells a cold reader what this actually is, set
   apart from the recognition copy above it. One pattern across
   every hero on the site rather than a per-page decision. */
.hero-hook__orient {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  font-weight: var(--weight-semi);
  color: var(--charcoal);
  max-width: 44ch;
  margin-top: var(--space-5);
}

/* Closing prompt. Was centred, argued at the time as the one band
   where centring is correct since it holds no left-aligned content
   of its own. That exception is withdrawn: the rail rule is
   simpler and more reliable than a per-band judgement call, and
   one page centring its closing CTA while another left-aligns it
   is exactly the inconsistency the rule exists to prevent. */
.cta-prompt {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  margin-bottom: var(--space-6);
}

/* Attribution under a pull quote. Sits tight to the quote it
   belongs to, at caption weight so it never competes with it. */
.pullquote-attrib {
  margin-top: var(--space-3);
  margin-left: var(--space-5);
  font-size: var(--size-attrib-name);
  font-weight: var(--weight-semi);
  color: var(--linework);
}

/* Format (d) is an attribution standard that follows the person, not
   the component, so a feature pullquote carries the same name,
   designation, employer and LinkedIn mark a card does. The element
   stays a <p>: it is a sibling of the blockquote rather than a child
   of a <figure>, so <figcaption> would be invalid here. Card markup
   is deliberately not reused; only the reading order is shared.
   A pullquote sits at display scale, so the role line stays regular
   weight at the smaller role size, keeping the block quiet enough
   that it does not read as a second headline under the quote. */
.pullquote-attrib__name { display: block; }

.pullquote-attrib__role {
  display: block;
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-regular);
  line-height: var(--lh-caption);
  margin-top: 2px;
}

.pullquote-attrib__in {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-2);
  color: var(--linework);
  transition: color .15s ease;
}

.pullquote-attrib__in:hover,
.pullquote-attrib__in:focus-visible { color: var(--charcoal); }

.pullquote-attrib__in-icon { display: block; }

/* Proof of the claim above it. Setting this in --linework was
   tried and rejected at render: it made a credential paragraph
   read as fine print, and evidence should never be quieter than
   the argument it supports. It steps back with a rule and a wider
   gap instead of with colour, so it reads as a separate move in
   the section rather than as a footnote to it. */
.credibility-line {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

.hero-felt__portrait {
  align-self: center;
  justify-self: end;
  width: 100%;
  max-width: 300px;
}

.hero-felt__portrait img,
.hero-felt__portrait .placeholder {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius);
}

@media (max-width: 768px) {
  .hero-felt__inner { grid-template-columns: 1fr; gap: var(--space-6); }
  /* justify-self:end is a desktop-only concern: once stacked, the
     portrait must start at the left rail like every other element
     on the page, or it is the one thing on mobile that does not. */
  .hero-felt__portrait { order: -1; max-width: 280px; justify-self: start; }
  .hero-felt__opening { max-width: none; }
}


/* ------------------------------------------------------------
   Hero — problem-hook variant             (all program pages)

   H1 scale (40px/1.15). Character budget: 40-55 target, ~65
   ceiling, which reads two lines at the 640px column. Headline
   emphasis here is the deliberate differentiator from the
   Home/My Story felt-recognition variant (A3).
   ------------------------------------------------------------ */

.hero-hook h1 {
  font-size: var(--size-h1);
  line-height: var(--lh-h1);
}

/* Program-page hero sub-line. Was --size-h3 in the heading serif
   at 600, which is what turned Inner Foundations' four-paragraph
   hero into a wall. Lead in the body face, capped narrower than
   the H1 above. NOTE: this is the typographic half of the fix
   only. Traction, Inner Awareness and Inner Foundations still run
   1.6x, 1.8x and 4.3x the 30-word hero-subhead ceiling; that is a
   Pass 2 trim, not a CSS problem. */
.hero-hook__sub {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  color: var(--charcoal);
  max-width: 48ch;
  margin-top: var(--space-5);
}

.hero-hook__more { margin-top: var(--space-6); }


/* ------------------------------------------------------------
   Process Arc — Tier 1 (light arc)

   Desktop: horizontal row. Numbered circle in THIS PAGE's lens
   accent (career blue on career pages, sage on inner-work ones),
   H3 stage name, then a one-line description at 11px linework.
   Simple arrow connectors between nodes.

   Mobile: stacked vertically with a thin connecting line rather
   than arrows (A1's locked mobile rule).

   The numbered-circle treatment is shared deliberately with
   Tier 2's stage numbering, so a visitor reads the two as the
   same journey at different zoom levels.

   Deliberately open and unboxed. A3 records this as a real
   semantic distinction from Diagnostic Frame: bordered means a
   bounded menu of options, open means a walked sequence. Do not
   "harmonise" these two later.
   ------------------------------------------------------------ */

.arc {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);

  /* Column gap only. gap: applied to rows too, and with the steps
     on subgrid that put 24px between the label and its own
     description on top of the label's margin. */
  column-gap: var(--space-6);
  row-gap: 0;

  /* Was running the full 912px rail against prose at 640, so it
     read as a stretched object rather than as part of the section
     it illustrates, and its descriptions had to drop to 11px to
     fit four columns across that width. */
  max-width: 720px;

}

/* Deliberately NOT subgrid. It was used here to align rows across
   the four columns and was inflating the label row to 52px for a
   20px line. With every label at one line and every node at 34px,
   the rows align on their own. */
.arc__step { position: relative; }

/* Sized so the LONGEST label, "Emotional Downshift", holds one
   line at this column width; the other three then follow. Set by
   measuring rendered line boxes rather than by estimate: at 17px
   it still wrapped, and subgrid was hiding that by reserving two
   lines in every column while only one label actually broke. */
.arc__name {
  font-size: 16px;
  line-height: 1.25;
  margin-bottom: var(--space-3);
}

.arc__num {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--white);
  font-family: var(--font-body);
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-semi);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-4);
}

/* The two-line floor that used to live here is REMOVED. It
   reserved 52px (--size-h3 x --lh-h3 x 2) so descriptions would
   align whether or not a stage name wrapped. With labels now
   sized to hold one line, it reserved a second line nothing ever
   used, which is the unexplained gap between every label and its
   description. Its arithmetic was also stale: it was computed
   from --size-h3 while the label had been stepped down to 16px.

   Alignment now comes from the labels genuinely fitting one line.
   If a future stage name is long enough to wrap, fix it by
   shortening the name or the label size, not by reinstating a
   floor that pads every column to cover one. */
.arc__name { margin-bottom: var(--space-3); }

.arc__desc {
  /* 11px was a consequence of the old full-rail width, not a
     considered choice. At 780px the columns can carry caption
     size, which is the smallest step that stays comfortably
     readable. */
  font-size: var(--size-caption);
  line-height: 1.55;
  color: var(--linework);
}

/* Arrow connector, sitting in the gap between nodes */
.arc__step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 16px;

  /* Centred on the midpoint between this node's right edge and
     the next node's left edge, so it holds its position at any
     column width. Short and heavy rather than a hairline spanning
     the full distance, which read as a stray rule. */
  left: calc(50% + (34px + var(--space-6)) / 2 - 26px);
  width: 44px;
  height: 3px;
  border-radius: 1.5px 0 0 1.5px;
  background: var(--linework);
}

.arc__step:not(:last-child)::before {
  content: "";
  position: absolute;

  /* A rotated bordered square was tried and rejected: rotation
     moves the visual tip away from the element's own box, so it
     both overlapped the shaft and overshot its end, and the
     corner read as a blob at this weight. A solid triangle has an
     unambiguous tip and butts flush to the shaft's end.

     Vertical: shaft is 3px at top 16, so its centre is 17.5. The
     triangle is 10px tall, so it starts at 12.5 to share that
     centre line. */
  top: 12.5px;
  left: calc(50% + (34px + var(--space-6)) / 2 + 18px);
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 9px solid var(--linework);
  z-index: 1;
}

@media (max-width: 768px) {
  .arc { grid-auto-flow: row; gap: var(--space-6); }

  /* Thin connecting line replaces the arrows when stacked */
  .arc__step:not(:last-child)::after {
    top: 34px;
    left: 16px;
    right: auto;
    width: 1px;
    height: calc(100% - 34px + var(--space-6));
  }
  .arc__step:not(:last-child)::before { display: none; }
}


/* ------------------------------------------------------------
   Process Arc — Tier 2 (fused stage unit)

   Stacked always. A3 records side-by-side as tested and beaten
   outright, so there is no desktop horizontal variant.

   Top zone uses --stage-tint, a cool component-internal wash
   that is NOT the sitewide section band tint. Carries stage
   number, name and kicker. Lower zone carries the description
   and the "You leave this stage with:" artifact line.

   Stage length varies non-monotonically across a sequence, so
   this must handle a long stage at any position.
   ------------------------------------------------------------ */

.stages > * + * { margin-top: var(--space-6); }

.stage {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
}

.stage__head {
  background: var(--stage-tint);
  padding: var(--space-5) var(--space-6);
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}

/* Card body was running the card's full 957px width, roughly 100
   characters a line against a comfortable 45 to 75. The card keeps
   its width; the prose inside it does not. */
.stage__body > p,
.stage__body > ul { max-width: var(--measure); }

.stage__num {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent-text);
  color: var(--white);
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-semi);
  display: flex;
  align-items: center;
  justify-content: center;
}

.stage__kicker {
  font-size: var(--size-attrib-role);
  line-height: var(--lh-caption);
  color: var(--linework);
  font-style: italic;
  margin-top: var(--space-2);
}

.stage__body { padding: var(--space-6); }

/* The artifact line carries the one tangible thing a client leaves
   with, and it was the quietest text on the card: caption size under
   a hairline, beneath 18px bullets. It now inherits body size rather
   than declaring one, so it cannot drift from the body scale later.
   The separation is carried by the rule, the gap, and the semibold
   "You build:" label instead of by type size. Its former 30rem cap
   (see the .caption rule further down) existed only to hold
   characters-per-line at 13px and is obsolete at body size. */
.stage__artifact {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  line-height: var(--lh-body);
}

.stage__artifact strong { font-weight: var(--weight-semi); }


/* ------------------------------------------------------------
   Diagnostic Modal                              (Home only)

   Format resolved as modal, not a dedicated child page, per
   master-checklist Item 28 — lower build-execution risk, no new
   route/page template, state stays in one place. Accepted
   trade-off: no shareable/linkable result URL (plan.md decision
   D deep-links the trigger via ?diagnostic=1 instead, which this
   component auto-opens on).
   ------------------------------------------------------------ */

.diag-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}

.diag-modal[hidden] { display: none; }

.diag-modal__scrim {
  position: absolute;
  inset: 0;
  background: rgba(35, 38, 43, 0.72);
}

.diag-modal__panel {
  position: relative;
  background: var(--surface);
  border-radius: var(--radius);
  max-width: 640px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  padding: var(--space-7) var(--space-6);
}

@media (max-width: 640px) {
  .diag-modal { padding: 0; align-items: flex-end; }
  .diag-modal__panel { max-width: 100%; max-height: 92vh; border-radius: var(--radius) var(--radius) 0 0; }
}

.diag-modal__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  background: var(--ground);
  color: var(--charcoal);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.diag-progress {
  font-size: var(--size-caption);
  color: var(--linework);
  margin-bottom: var(--space-5);
}

.diag-q h3 {
  font-size: var(--size-h3);
  line-height: 1.4;
  margin-bottom: var(--space-6);
  padding-right: var(--space-7);
}

.diag-q__options { display: flex; flex-direction: column; gap: var(--space-3); }

.diag-option {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--ground);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-5);
  font-size: var(--size-body);
  line-height: 1.5;
  cursor: pointer;
  color: var(--charcoal);
}

.diag-option { transition: border-color var(--transition), background var(--transition); }

.diag-option:hover,
.diag-option:focus-visible { border-color: var(--accent-career); background: var(--surface); }

/* Email gate removed (remediation): .diag-email / .diag-error styled
   the old email-capture screen, which no longer exists — the report
   renders straight from Phase 3, and the Netlify submission is
   anonymous. Removed rather than left as dead CSS. */

.diag-interstitial p {
  font-size: var(--size-body);
  line-height: var(--lh-body);
  margin-bottom: var(--space-6);
}

.diag-result h3 {
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  margin-bottom: var(--space-4);
}

.diag-result p { font-size: var(--size-body); line-height: var(--lh-body); }
.diag-result p + p { margin-top: var(--space-4); }

.diag-mismatch { color: var(--linework); font-style: italic; }

/* Single confidence label (remediation 2.3) — one of three tiers,
   never a badge that could contradict a mismatch note on the same
   screen; scoring.js's own cap on the tier is what guarantees that,
   this just renders whichever tier it's given. */
.diag-tier {
  display: inline-block;
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: var(--space-3);
}
.diag-tier--strong { color: var(--accent-career); }
.diag-tier--leaning { color: var(--linework); }
.diag-tier--unclear { color: var(--linework); }

/* All four programs always get a bar (remediation 2.1). An untaken
   branch's bars render visibly dimmer with a note, rather than as a
   peer result next to programs the run actually discriminated
   between (2.2). */
.diag-bars { margin: var(--space-6) 0; }
.diag-bar { margin-bottom: var(--space-4); }
.diag-bar__label { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--size-caption); margin-bottom: var(--space-2); }
.diag-bar__track { height: 8px; background: var(--ground); border-radius: 4px; overflow: hidden; }
.diag-bar__fill { height: 100%; background: var(--accent-career); border-radius: 4px; }

.diag-bar--untaken { opacity: 0.55; }
.diag-bar--untaken .diag-bar__fill { background: var(--linework); }
.diag-bar__note {
  font-style: italic;
  font-weight: var(--weight-regular);
  text-transform: none;
  letter-spacing: normal;
}

/* Framed group with a heading (remediation 2.4), capped at two
   entries by scoring.js's selectRuleOuts — never the old unbounded
   stack of every low-scoring program's own message. */
.diag-ruleouts {
  margin-top: var(--space-6);
  padding: var(--space-5);
  background: var(--ground);
  border-radius: var(--radius-sm);
}

.diag-ruleouts__heading {
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--linework);
  margin-bottom: var(--space-3);
}

.diag-ruleouts p {
  font-size: var(--size-caption);
  color: var(--linework);
}

.diag-ruleouts p + p { margin-top: var(--space-3); }

/* Report expansion: Sections C, B, D, E render below the existing
   result block, built from report.js's buildReport output. Section A
   (the mirror) is an appendix below the actions block instead of
   living in this group (R1, layout pass) — .diag-report is reused
   for both groups, .diag-report--appendix zeroes the top margin the
   base rule sets, since the rule above the appendix already provides
   the separation. Section A stays a definition list, not a table —
   probe as the term, the person's verbatim answer as the
   definition. */
.diag-report { margin-top: var(--space-7); }
.diag-report--appendix { margin-top: 0; }

.diag-report__section + .diag-report__section { margin-top: var(--space-6); }

.diag-report__heading {
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  margin-bottom: var(--space-4);
}

.diag-report__section p { font-size: var(--size-body); line-height: var(--lh-body); }
.diag-report__section p + p { margin-top: var(--space-4); }

/* The pointer line under Section C, added when Section A moved out
   of this group — tells the reader the verbatim record still exists,
   just further down. */
.diag-report__pointer {
  font-size: var(--size-caption);
  color: var(--linework);
  font-style: italic;
}

.diag-sectionA__group-heading {
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--linework);
  margin: var(--space-5) 0 var(--space-3);
}
.diag-sectionA__group-heading:first-child { margin-top: 0; }

.diag-sectionA__list { margin: 0; }
.diag-sectionA__list dt {
  font-size: var(--size-caption);
  color: var(--linework);
  margin-top: var(--space-3);
}
.diag-sectionA__list dt:first-child { margin-top: 0; }
.diag-sectionA__list dd {
  font-size: var(--size-body);
  line-height: 1.5;
  margin: var(--space-1) 0 0;
}

/* Separates the argument (C, B, D, E, actions) from the Section A
   appendix. */
.diag-appendix-rule {
  margin: var(--space-7) 0 var(--space-6);
  border: 0;
  border-top: 1px solid var(--border);
}

/* Two rows (R2, layout pass). Row one, forward action: the program
   and booking, exactly one solid per renderActions' confidence-tier
   logic — never two, that is a locked violation regardless of which
   control carries it. Row two, artifact action: Save as PDF and
   Share, always both outline, since saving and sharing happen after
   the decision the row above is for. */
.diag-actions { margin-top: var(--space-7); }

.diag-actions__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}
.diag-actions__row + .diag-actions__row { margin-top: var(--space-4); }

.diag-actions__control {
  flex: 1 1 auto;
  text-align: center;
  min-width: 180px;
}

.diag-actions__note {
  display: inline-block;
  margin-top: var(--space-3);
}

.diag-share__status {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--size-caption);
  color: var(--linework);
}

/* PDF export (remediation 2.5): print stylesheet + window.print(),
   no library. The report is composed for print specifically, not a
   screenshot of the on-screen panel — see modal.js's
   renderPrintReport. Scoped with :has() so this never touches an
   ordinary page print: the isolation rules only activate when a
   .diag-print-report element actually exists in the document, which
   only happens once a diagnostic result has rendered. */
.diag-print-report { display: none; }

@media print {
  /* A4 as the base size, margins generous enough to stay readable if
     the PDF is ever printed on Letter instead — Letter is 18mm
     shorter than A4, so a plain A4 margin would run content off the
     bottom of a Letter page. */
  @page {
    size: A4;
    margin: 20mm 16mm;
  }

  /* C20: this was visibility: hidden, which hides paint but not
     layout -- the rest of the page (a full marketing page: hero,
     every section, footer) stayed in normal flow at full height and
     the print engine paginated against that, not against the report.
     display: none removes it from layout instead. The selector has
     to preserve three things, not just the report itself: its
     descendants (the report's own content), and its full ancestor
     chain (.diag-modal, .diag-modal__panel, body, html) -- an
     ancestor caught by this rule would take the report down with it,
     since display: none on a container removes its whole subtree
     regardless of the report's own position: absolute. Measured
     during C20: this rule alone took the report from 6-7 printed
     pages to 3-4, on report content that never changed. */
  body:has(.diag-print-report)
    *:not(.diag-print-report):not(.diag-print-report *):not(:has(.diag-print-report)) {
    display: none;
  }
  body:has(.diag-print-report) .diag-print-report {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    padding: var(--space-6);
  }
  body:has(.diag-print-report) .diag-modal {
    position: static;
  }
  body:has(.diag-print-report) .diag-modal__panel {
    position: static;
    max-height: none;
    overflow: visible;
    padding: 0;
  }
  body:has(.diag-print-report) .diag-modal__scrim,
  body:has(.diag-print-report) .diag-modal__close {
    display: none;
  }
  .diag-print-report h2 { font-size: var(--size-h2); margin-bottom: var(--space-2); }
  .diag-print-report__date { color: var(--linework); font-size: var(--size-caption); margin-bottom: var(--space-6); }
  .diag-print-report h3 { font-size: var(--size-h3); margin-bottom: var(--space-3); }
  .diag-print-report h4 { font-size: var(--size-body); margin: var(--space-6) 0 var(--space-3); }
  .diag-print-report__scores { border-collapse: collapse; margin: var(--space-5) 0; }
  .diag-print-report__scores td { padding: var(--space-2) var(--space-5) var(--space-2) 0; }

  /* C20: base.css's body { font-size: 18px; line-height: 1.6 } is
     screen-tuned and was never reset in here, so every paragraph, the
     appendix answers, and the score table cells were rendering at
     full screen size in print. 10pt/1.4 measured against real PDF
     output during C20. */
  .diag-print-report p,
  .diag-print-report dd,
  .diag-print-report dt,
  .diag-print-report td {
    font-size: 10pt;
    line-height: 1.4;
  }

  /* Sections C, B, D, E, then the appendix rule, then Section A
     (layout pass): each section stays on a single page rather than
     splitting across a break. */
  .diag-print-report__section { break-inside: avoid; margin-top: var(--space-6); }
  .diag-print-report__section h3 { font-size: var(--size-h3); margin-bottom: var(--space-3); }
  .diag-print-report__section h4 { font-size: var(--size-body); margin: var(--space-5) 0 var(--space-2); }
  .diag-print-report__section dl { margin: 0; orphans: 3; widows: 3; }
  .diag-print-report__section dt { font-size: var(--size-caption); color: var(--linework); margin-top: var(--space-2); }
  .diag-print-report__section dt:first-child { margin-top: 0; }
  .diag-print-report__section dd { margin: var(--space-1) 0 0; }

  /* C20 reopened: Section A (the appendix) is always the last of
     these sections, and it is routinely taller than a full printed
     page, since it quotes back every question asked. break-inside:
     avoid can't honor "stay on one page" for a box that doesn't fit
     on any single page, and Chromium's fallback was to push the
     whole thing to a fresh page rather than let it start filling the
     space left on the current one -- on a both-branch run that left
     page 2 at roughly a third full (444-687 characters against
     ~1,500 on a full page) before the appendix even started. Exempt
     only the last section from the rule; the four short sections
     above it (C, B, D, E) keep break-inside: avoid, since those are
     the ones the rule was written for. widows/orphans is a second,
     independent safeguard: it stops a single trailing dt/dd pair
     from ever being stranded alone on its own page once the appendix
     is flowing normally, which break-inside can't prevent by itself.
     widows/orphans lives on the dl declaration above, not here. */
  .diag-print-report__section:last-of-type { break-inside: auto; }

  .diag-print-report__appendix-rule {
    margin: var(--space-6) 0;
    border: 0;
    border-top: 1px solid var(--border);
  }
}


/* ------------------------------------------------------------
   Filter Bar                        (standalone Testimonials)

   Sticky on scroll, solid Ground background with a thin bottom
   border so grid content never bleeds through while scrolling
   underneath. Active state is solid CHARCOAL, deliberately not a
   lens-accent colour: this page's filter set spans all three
   registers (Transition/Traction are career, Inner Work is
   inner-work), and using either branch's accent would misleadingly
   suggest the page favours one lens.
   ------------------------------------------------------------ */

/* The bottom rule previously spanned the whole viewport while the
   pills sat inset at the container, so the only full-bleed line on
   the site cut across an otherwise railed page. Rule now starts
   and ends at the rail like every other. */
.filter-bar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--ground);
  padding-block: var(--space-4);
  padding-inline: max(var(--gutter), calc((100% - var(--rail)) / 2));
}

.filter-bar__inner {
  max-width: var(--rail);
  margin-inline: auto;
  border-bottom: 1px solid var(--border);
  padding-bottom: var(--space-4);
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.filter-pill {
  transition: background var(--transition), border-color var(--transition), color var(--transition);
  background: transparent;
  border: 0.5px solid var(--border);
  color: var(--charcoal);
  border-radius: 999px;
  padding: var(--space-3) var(--space-5);
  font-size: var(--size-caption);
  font-weight: var(--weight-medium);
  cursor: pointer;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.filter-pill[aria-pressed="true"] {
  background: var(--charcoal);
  border-color: var(--charcoal);
  color: var(--white);
}


/* ------------------------------------------------------------
   Testimonials grid           (standalone Testimonials page)

   display:grid rather than the originally-suggested masonry:
   the source file's own build note calls this "newly viable"
   now that entries are length-capped, making card heights far
   more uniform than before, and simpler than a JS masonry lib.
   ------------------------------------------------------------ */

.t-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}

/* Filtering (Phase 3) toggles this class; it must never be the
   thing that removes a card from the DOM (A3's explicit
   instruction, to avoid layout thrashing on every click). */
.t-grid .t-card.is-hidden { display: none; }

@media (max-width: 900px) {
  .t-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .t-grid { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------
   Split                    (generic 50/50 two-column layout)

   Used for Ganga Tattva's hero (river visual | video) and
   tree/root section (blurb | tree visual) — two genuine split
   blocks per ganga-tattva-planning-checklist.md, not a caption
   beside an image. A1's locked mobile rule applies: stack
   vertically, always.
   ------------------------------------------------------------ */

.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-7);
  align-items: center;
}

@media (max-width: 768px) {
  .split { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------
   Video Embed                                (Ganga Tattva hero)

   16:9, responsive width, custom poster (placeholder for now),
   native controls, no autoplay. Desktop: right half of the hero
   split, river/water visual left. Mobile: stacks below.
   Mechanical/structural component, not register-dependent, so
   it's built now even though the Ganga register pass gated the
   rest of this page's visual work (A3a).
   ------------------------------------------------------------ */

.video-embed {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  overflow: hidden;
}

.video-embed .placeholder { width: 100%; height: 100%; border-radius: var(--radius); }


/* ------------------------------------------------------------
   CTA Pairing — Symmetric                     (Ganga Tattva only)

   Unlike the primary register's asymmetric CTA Pairing, Ganga
   Tattva's two CTAs (WhatsApp Community, Private Session) are
   equal-weight by design. Both solid-filled, identical size,
   ochre fill (--accent, which body.ganga already remaps to
   --accent-spiritual, so no separate colour rule is needed here).
   ------------------------------------------------------------ */

.cta-pair-sym {
  display: flex;
  gap: var(--space-5);
  justify-content: center;
  flex-wrap: wrap;
}

.cta-pair-sym /* Solid fills that carry text use --accent-text, not --accent.
   The token split is by "does text sit on this", not by "is this
   text or a fill": white on #B8763E is 3.68:1 and fails, white on
   #89592F is 5.94:1 and passes. Decorative marks with nothing on
   top of them keep the locked hue. Measured, both ways. */
.btn { flex: 0 1 240px; text-align: center; }


/* ------------------------------------------------------------
   Hero — uniform intro variant           (Inner Compass only)

   Standard H1 styling, same as every other page's hero. Carries
   no lens-accent colour: Inner Compass spans all three registers
   (career, inner-work, the Ganga Tattva bridge), so tinting
   toward any one branch would misrepresent the page's role.
   ------------------------------------------------------------ */

/* Sub-line, Inner Compass. Same descale as the other two hero
   variants so all three now share one treatment instead of three
   near-identical serif-bold steps. */
/* The marquee diagram is an 11:6 landscape that was squeezed into
   a 640px text column and stacked under the copy, so it read as an
   afterthought and was hard to actually see. The wrapper now runs
   the full rail and only the prose inside it is capped at measure,
   which lets the diagram breathe and gives this hero the second
   element it always had. */
.hero-uniform > h1,
.hero-uniform > p { max-width: var(--measure); }

.hero-uniform__sub {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  color: var(--charcoal);
  max-width: 48ch;
}


/* ------------------------------------------------------------
   Image Lightbox — Zoomable trigger        (Inner Compass)

   Structure and hover affordance only here; open/zoom/pan/
   dismiss behaviour is wired in Phase 3 JS. Click-to-open
   full-viewport overlay, dark scrim, zoom via scroll/pinch,
   drag-to-pan past 100%, dismiss via close button, click-outside,
   or Escape — all three, not just one (A3).

   Hover state: subtle opacity shift plus a small expand-icon
   overlay, top-right corner, so the click affordance is
   discoverable rather than hidden.
   ------------------------------------------------------------ */

.lightbox-trigger {
  position: relative;
  display: block;
  border: 0;
  background: none;
  padding: 0;
  cursor: zoom-in;
  width: 100%;
  border-radius: var(--radius);
  overflow: hidden;
}

.lightbox-trigger:hover img,
.lightbox-trigger:focus-visible img,
.lightbox-trigger:hover .placeholder,
.lightbox-trigger:focus-visible .placeholder { opacity: 0.85; }

.lightbox-trigger img,
.lightbox-trigger .placeholder { transition: opacity var(--transition); }

/* Trigger is now an <a>, per GLightbox's expected markup (was a
   <button> when only a non-clickable placeholder sat inside it). */
.lightbox-trigger:link,
.lightbox-trigger:visited { text-decoration: none; }

.lightbox-trigger__icon {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 2px 8px rgba(35, 38, 43, 0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--charcoal);
}


/* ------------------------------------------------------------
   Work With Me hero split                (prose left, cards right)

   Own grid, not a reuse of .hero-felt__inner -- that one is tuned
   for a narrow portrait photo (1fr/0.46fr) and doesn't fit a
   two-card column. Even split, prose and cards both in natural DOM
   order (no CSS `order` swap needed, so heading order matches
   visual order for free).
   ------------------------------------------------------------ */

.work-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: start;
}

@media (max-width: 768px) {
  .work-hero { grid-template-columns: 1fr; gap: var(--space-6); }
}


/* ------------------------------------------------------------
   Booking Cards                          (Work With Me hero)

   White surface, H3 title, Caption meta line (duration/price),
   bullet list in Body, full-width button. Asymmetric per CTA
   Pairing's own logic: Discovery Call (entry point, lower
   commitment) gets the solid filled button; Working Session
   (continuing clients) gets the outlined button.

   Two layout variants, context-dependent:
   - .booking-grid            side-by-side, full-width section
   - .booking-grid--stack     stacked-vertical, half-width column

   A3's own finding: side-by-side inside a half-width column
   squeezes each card to ~150px, too narrow for its bullet list.
   Work With Me's hero pairs this against intro prose in a split,
   so it uses the stacked-vertical variant specifically.
   ------------------------------------------------------------ */

.booking-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
}

.booking-grid--stack { grid-template-columns: 1fr; }

.bcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
}

/* Semantically h2 (a heading-order fix: the page's own h1 must
   precede these in the outline, which h3 could not guarantee once
   Booking Cards render ahead of the intro in a two-column split).
   Held at H3's visual scale so the card doesn't inherit h2's
   larger 28px size sitewide. */
.bcard__title {
  font-size: var(--size-h3);
  line-height: var(--lh-h3);
}

.bcard__meta {
  font-size: var(--size-caption);
  color: var(--linework);
  margin-top: var(--space-2);
}

.bcard__list {
  margin-top: var(--space-5);
  flex: 1;
}

.bcard__list li {
  font-size: var(--size-track-bullet);
  line-height: 1.55;
  padding-left: var(--space-4);
  position: relative;
}

.bcard__list li + li { margin-top: var(--space-3); }

.bcard__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

.bcard__cta { margin-top: var(--space-6); }

/* Compact spacing so the two stacked cards combined stay within the
   height of the hero prose column beside them (Work With Me only —
   .booking-grid--stack is not used anywhere else). */
.booking-grid--stack { gap: var(--space-3); }
.booking-grid--stack .bcard { padding: var(--space-3); }
/* The stacked variant previously compressed everything to fit
   four bullets beside the hero: line-height 1.3 and 4px between
   items, which made the cards read as dense blocks rather than as
   something you scan. With three bullets there is room to breathe,
   and the pair still stands at roughly the hero copy's height. */
.booking-grid--stack .bcard__meta { margin-top: var(--space-2); }
.booking-grid--stack .bcard__list { margin-top: var(--space-4); }
.booking-grid--stack .bcard__list li { line-height: var(--lh-body); }
.booking-grid--stack .bcard__list li + li { margin-top: var(--space-3); }
.booking-grid--stack .bcard__cta { margin-top: var(--space-5); }

@media (max-width: 768px) {
  .booking-grid { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------
   Ladder Flow                    (Work With Me, "How it works")

   No A3 entry existed for this component. Previous hand-coded
   version (separate SVG rail column + independently-positioned
   HTML chips) never actually aligned the rails to the chips and
   cascaded the wrong direction — replaced with a single finished
   SVG illustration (rails, rungs, chips, and copy all baked into
   one asset) supplied directly by Arvind, at its native ~560:350
   ratio so the baked-in 13px text stays legible.
   ------------------------------------------------------------ */

.ladder {
  /* Was 560px centred inside a 912px rail, so the diagram was
     constricted by its own box and then floated away from the
     left edge everything else starts at. The SVG carries internal
     margins of its own, which compounded it. */
  max-width: var(--rail);
  margin-inline: 0;
}

.ladder img { width: 100%; display: block; }


/* ------------------------------------------------------------
   Loop Diagram        (Inner Foundations, Inner Compass, Awareness)

   Node labels at H3 scale in IBM Plex Serif, matching Process Arc
   Tier 1's node-name treatment so the two read as one visual
   family at increasing depth rather than two diagram styles.
   Sage outline on white.

   5-step (Event -> Interpretation -> Emotion -> Action ->
   Experience): the final node fills solid sage as endpoint
   emphasis.

   7-step deep loop (Inner Awareness Intensive): TWO nodes fill
   solid, Coping Style and Reinforcement, following the source
   material's own statement that these are the page's central
   mechanism. Not an arbitrary emphasis choice.

   Built in HTML rather than SVG so labels reflow and stay
   readable at every width without a separate mobile asset.
   ------------------------------------------------------------ */

.loop {
  display: flex;
  flex-wrap: wrap;
  align-items: center;

  /* Was centred, which floated a five-node chain in the middle of
     the rail while every other element on the page started at its
     left edge. */
  justify-content: flex-start;
  gap: var(--space-4) 0;

  /* The chain sits outside .text-col, so it never inherited the
     stack spacing and butted straight against the paragraph above
     it. */
  margin-top: var(--space-6);
}

/* Caption belongs to the chain above it and shares its left edge,
   rather than centring under the middle of a diagram that is
   itself wider than the caption. */
.loop__caption {
  margin-top: var(--space-4);
  max-width: var(--measure);
}

/* Each node carries its own incoming arrow, so the two can never be
   split across a line break and leave an arrow pointing at nothing. */
.loop__item {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.loop__item:not(:first-child)::before {
  content: "\2192";
  color: var(--accent-inner);
  font-size: var(--size-caption);
  line-height: 1;
  padding: 0 var(--space-3);
}

.loop__node {
  border: 1.5px solid var(--accent-inner);
  border-radius: 999px;
  background: var(--surface);
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-heading);
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  line-height: 1.3;
  color: var(--charcoal);
  white-space: nowrap;
}

.loop__node--fill {
  background: var(--accent-inner);
  border-color: var(--accent-inner);
  color: var(--white);
}

.loop__arrow {
  color: var(--accent-inner);
  font-size: var(--size-caption);
  line-height: 1;
  flex: 0 0 auto;
}


/* ------------------------------------------------------------
   Bullet List
   Generic plain-bullet list: accent dot, Body text. No card, no
   border. Used wherever a page needs a bulleted list with no
   named component of its own (Work With Me's "This work may be
   a fit if", Loop Diagram's intervention points).
   ------------------------------------------------------------ */

.bullet-list li {
  font-size: var(--size-body);
  line-height: var(--lh-body);
  padding-left: var(--space-5);
  position: relative;
}

.bullet-list li + li { margin-top: var(--space-3); }

.bullet-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}


/* ------------------------------------------------------------
   Signpost                    (Inner Awareness Intensive Tier 2)

   Bridges toward Ganga Tattva. A3 specs this as an outlined
   pill/tag in spiritual-accent ochre; this page's actual locked
   copy (page-copy-master) is a full paragraph, not a ~6-word tag,
   so the outline/border treatment is kept but sized to its real
   content rather than forced into pill proportions.

   Ochre here is deliberate even though the page's own lens is
   sage: A1 reuses the same accent already on this component and
   on Ganga Tattva's CTAs specifically so a visitor who clicks
   through sees the colour continue rather than change.
   Placement: near the add-on/support section on Tier 2 only,
   never Tier 1.
   ------------------------------------------------------------ */

.signpost {
  border: 1.5px solid var(--accent-spiritual);
  border-radius: var(--radius-sm);
  padding: var(--space-6);
  max-width: var(--measure);
  margin-inline: auto;
}

.signpost p {
  font-size: var(--size-body);
  line-height: var(--lh-body);
}

.signpost a {
  display: inline-block;
  margin-top: var(--space-4);
  color: var(--accent-spiritual);
  font-weight: var(--weight-semi);
  text-decoration: underline;
  text-underline-offset: 3px;
}


/* ------------------------------------------------------------
   Diagnostic Frame                   (Traction Intensive Tier 1)

   Two bordered stages sharing an identical treatment. The border
   does real semantic work: it signals "bounded menu of options",
   true of Traction's six Friction Points and false of a walked
   sequence like Transition's five stages. A3 states explicitly
   that this treatment must NOT be reused on Process Arc, and
   vice versa. Bordered = menu. Open = sequence.

   Stage badge colour signals diagnostic phase versus application
   phase, NOT branch: blue on Diagnose, sage on Go Deep, on a page
   whose own lens is career throughout.

   The six Friction Points carry no numbers or letters. They are
   genuinely a menu, not an order.
   ------------------------------------------------------------ */

.dframe > * + * { margin-top: var(--space-6); }

.dframe__stage {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-6);
  background: var(--surface);
}

.dframe__badge {
  display: inline-block;
  background: var(--accent-career);
  color: var(--white);
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-semi);
  letter-spacing: 0.04em;
  padding: var(--space-2) var(--space-4);
  border-radius: 999px;
  margin-bottom: var(--space-4);
}

.dframe__stage--deep .dframe__badge { background: var(--accent-inner); }

.dframe__lead { margin-bottom: var(--space-6); }

.fpoints {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6) var(--space-7);
  margin-top: var(--space-6);
}

/* Label + short rule + description. Deliberately reuses the
   header-plus-divider language already set by Track Cards, so it
   reads as system vocabulary rather than a page-specific
   invention (A3, "Option C"). */
.fpoint__label { margin-bottom: var(--space-2); }

.fpoint__rule {
  width: 22px;
  height: 2px;
  border: 0;
  margin: 0 0 var(--space-3);
  background: var(--accent-career);
}

.fpoint__desc {
  font-size: var(--size-track-bullet);
  line-height: 1.6;
  color: var(--linework);
}


/* ------------------------------------------------------------
   Reference List              (Traction Intensive Tier 2)

   The six Friction Points in full paragraph form. Needed a
   treatment distinct from both Diagnostic Frame (too menu-like
   and bordered for reference material) and a plain paragraph
   stack, which A3 records as reading like "a manual" and
   rejects by name.

   Eyebrow label, promoted lead sentence at H3 scale, then the
   rest of the paragraph dropped to smaller secondary text.
   Hierarchy carries the density rather than decoration.

   Two-column grid, chosen specifically to break the manual read.
   A radial layout was explored and rejected: circular language
   is reserved for Inner Compass's psychological register, and
   borrowing it on a career page would set a cross-register
   precedent nobody has decided on.
   ------------------------------------------------------------ */

.reflist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-8) var(--space-7);
}

.refitem__eyebrow { margin-bottom: var(--space-3); }

.refitem__lead {
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  line-height: var(--lh-h3);
  font-weight: var(--weight-semi);
  margin-bottom: var(--space-3);
}

.refitem__rest {
  font-size: var(--size-track-bullet);
  line-height: 1.65;
  color: var(--linework);
}

@media (max-width: 768px) {
  .fpoints,
  .reflist { grid-template-columns: 1fr; }
}


/* ------------------------------------------------------------
   FAQ Block — Flat                    (Tier 1 program pages)
   Capped at 2-3 items. Always expanded, no interaction: this is
   a final friction-removal step before the CTA, not a section
   a visitor should have to open (GTM 3.2).
   ------------------------------------------------------------ */

.faq-flat > * + * { margin-top: var(--space-6); }
.faq-flat__q { margin-bottom: var(--space-3); }


/* ------------------------------------------------------------
   Pull-Quote

   Breaks out of the text column, steps up to headline serif,
   charcoal, with a lens-accent rule. Used sparingly, at most one
   per page. Also the designated treatment for short standalone
   testimonial excerpts, and reused as the routing callout on
   program pages.

   Routing callouts always point to a discovery conversation and
   never name a program: burnout spans workable depletion to
   clinical intensity, and no static page can safely make that
   call (GTM 3.2).
   ------------------------------------------------------------ */

.pullquote {
  border-left: 3px solid var(--accent);
  padding: var(--space-2) 0 var(--space-2) var(--space-5);
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  line-height: 1.45;
}

/* Featured pull quote. The plain .pullquote carries the same
   accent left border as a .t-card, so next to a card row it read
   as "one more testimonial, slightly bigger". Stepping the SIZE up
   was tried first and rejected at render: at --size-h2 in a narrow
   column it became five short lines and looked worse than two long
   ones. The card device is the border, so absence of the border is
   the signal. Used where a client independently states the claim
   the page has just made. */
.pullquote--feature {
  border-left: 0;
  padding: 0;
  max-width: 46ch;
}

.pullquote--feature + .pullquote-attrib { margin-left: 0; }

.pullquote a {
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.credibility p {
  font-size: var(--size-body);
  line-height: var(--lh-body);
}

.invest__price {
  font-family: var(--font-heading);
  font-size: var(--size-h2);
  line-height: var(--lh-h2);
}


/* ------------------------------------------------------------
   Hero — structural variant                  (Offerings only)

   A genuinely third hero case. Headline-worthy like the
   problem-hook variant, but explicitly not felt content per
   GTM 3.4 ("no felt hook"). Resolved in A3 as: H1 weight, so it
   still carries presence, paired with plain Body-style support
   text at 15px rather than the Lead-style felt subhead. Keeps
   the structural-clarity register distinct from the emotional
   one used on program pages.
   ------------------------------------------------------------ */

.hero-structural h1 {
  font-size: var(--size-h1);
  line-height: var(--lh-h1);
}

/* H3-scale: marked up as <p> not <h3>, since it's supporting
   prose, not a section heading. */
/* Offerings is the one hero that is deliberately NOT felt: A3
   pairs its H1 with plain Body-style support so the structural
   register reads differently from a program page's emotional
   hook. The build had it at --size-h3 heading serif 600, the same
   as every other hero, which collapsed that distinction and left
   --size-offerings-lead defined but never used. */
.hero-structural__support {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  color: var(--linework);
  max-width: 52ch;
  margin-top: var(--space-5);
}


/* ------------------------------------------------------------
   Track Cards                        (My Story, Offerings)

   Reverse-engineered in A3 from the live site's "two parallel
   tracks" section, re-skinned in locked tokens. Centred H2,
   two equal columns, short divider under each title coloured
   per-card in that track's lens accent, bullets below.
   No button, no CTA — that is what separates it from
   Booking Cards despite the shared surface treatment.

   Deliberately NOT numbered, ranked or connected: the four
   programs are peers grouped by branch, never a ladder
   (program-and-page-canon.md, GTM 3.4).
   ------------------------------------------------------------ */

.track-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
}

.track-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-6);
}

.track-card__divider {
  width: 36px;
  height: 2px;
  border: 0;
  margin: var(--space-3) 0 var(--space-4);
  background: var(--accent-career);
}

.track-card--inner .track-card__divider { background: var(--accent-inner); }

.track-card__intro {
  font-size: var(--size-track-bullet);
  line-height: 1.6;
  color: var(--linework);
}

.track-card__list { margin-top: var(--space-4); }

.track-card__list li {
  font-size: var(--size-track-bullet);
  line-height: 1.55;
  padding-left: var(--space-4);
  position: relative;
}

.track-card__list li + li { margin-top: var(--space-3); }

.track-card__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-career);
}

.track-card--inner .track-card__list li::before { background: var(--accent-inner); }

.track-card__list strong { font-weight: var(--weight-semi); }

/* Sequencing note, moved inside the Inner Work card itself (was a
   shared caption floating under the whole grid, disconnected from
   the one card it actually applies to). Career gets no equivalent
   footer since the note doesn't apply there. */
.track-card__note-divider {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--space-5) 0 var(--space-4);
}

.track-card__note {
  font-size: var(--size-track-bullet);
  line-height: 1.6;
  color: var(--linework);
  font-style: italic;
}


/* ------------------------------------------------------------
   Program Primer Card                    (Offerings only, x4)

   White surface, 3px top border coloured BY BRANCH rather than
   per-program, reinforcing the grouping established one section
   earlier in "Find your branch".

   Price removed, duration kept. A3 records these as two separate
   decisions and flags the price removal as superseding B3.4's
   bundled "amount + duration" note in page-copy-master.md.
   Duration stays because it does real self-selection work here:
   Foundations' 4-6 weeks against the others' 6-8 is a genuine
   differentiator at the moment a visitor is placing themselves.

   CTA is a plain text link, not a button: four buttons on one
   page would compete with the page's single true button-weight
   action, the closing Discovery Call.
   ------------------------------------------------------------ */

.primer-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* title / blurb / quote / duration / cta */
  grid-template-rows: auto auto auto auto auto;
  gap: var(--space-5);
  align-items: stretch;
}

.primer {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent-career);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  padding: var(--space-5);

  /* Was a flex column, which packed each card independently.
     Spanning the parent's rows makes every card share one set of
     baselines, so a two-line title in one card reserves two lines
     in all four and everything below stays level. */
  display: grid;
  grid-row: span 5;
  grid-template-rows: subgrid;
  row-gap: 0;
}

.primer--inner { border-top-color: var(--accent-inner); }

.primer__title { margin-bottom: var(--space-3); }

.primer__title { margin-bottom: var(--space-4); }

.primer__blurb {
  font-size: var(--size-primer-blurb);
  line-height: 1.6;
  color: var(--linework);
}

/* A third, distinct quote treatment: no attribution, unlike
   Testimonial Card, and not full headline weight, unlike
   Pull-Quote. A bare felt-hook line. */
.primer__quote {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--size-caption);
  line-height: 1.5;
  color: var(--charcoal);

  /* The felt-experience line is the one thing on this card a
     reader recognises themselves in, so it gets air on both sides
     rather than sitting in the same rhythm as the blurb above it.
     Whitespace does the emphasis here; the size stays put so the
     card keeps its quiet register. */
  margin-top: var(--space-5);
  margin-bottom: var(--space-2);
}

.primer__duration {
  font-size: var(--size-attrib-role);
  line-height: var(--lh-caption);
  color: var(--linework);
  margin-top: var(--space-4);
  margin-bottom: var(--space-5);
}

/* margin-top:auto pins the CTA to the bottom of the flex column so
   all four sit on one line regardless of how long each blurb runs. */
/* Exploring a program is the primary outcome of this page, so
   the card CTA gets a real button affordance rather than a text
   link. Outline, not solid: solid fill is reserved sitewide for
   the diagnostic, and four solid slabs in a row would flatten
   that hierarchy. The card itself is already a bordered object,
   so an outlined control sits inside it naturally.

   The rule above it is gone: a border plus a button was two
   separators doing one job. */
.primer__cta {
  align-self: end;
  padding-top: var(--space-5);
}

/* Fixed height rather than auto: "Explore Inner Awareness Intensive"
   wraps to two lines where the other three fit one, which would
   otherwise leave its divider rule sitting higher than the rest.
   44px also satisfies the touch-target minimum. */
.primer__cta a {
  display: block;
  min-height: 44px;
  font-size: 15px;
  font-weight: var(--weight-semi);
  color: var(--accent-career);
  text-decoration: none;
}

.primer--inner .primer__cta a { color: var(--accent-inner-text); }

.primer__cta a { transition: color var(--transition); }
.primer__cta a {
  display: block;
  text-align: center;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-weight: var(--weight-semi);
  text-decoration: none;
  transition: background var(--transition), color var(--transition);
}

.primer__cta a:hover {
  background: var(--accent-text);
  color: var(--white);
}

/* Small text needs a narrower box to land at the same character
   count: --measure is calibrated for 18px body, so 13px running
   640px reads about 98 characters against a comfortable 45 to 75.
   Anything below Body caps here instead. */
.measure-sm { max-width: 30rem; }

/* Applied where small text was already inheriting the full 18px
   measure: stage artifact lines and standalone captions. Caught by
   tools/render-check.mjs, which counts characters rather than
   pixels, so it sees what a pixel cap alone cannot. */
/* .stage__artifact was pinned here at 30rem to preserve
   characters-per-line while it rendered at caption size. It now
   renders at body size and takes --measure from .stage__body > p,
   matching the bullets above it, so the override and the
   specificity workaround it needed are both gone. */
.caption { max-width: 30rem; }

/* Ganga Tattva sits outside the four-program grouping and is
   deliberately quieter — footnote weight, never a fifth peer
   card (page-copy-master visual notes, brand-offerings-canon). */
/* Width/positioning now comes from .text-col (paired in markup)
   so this shares the page's container left edge instead of
   self-centering independently at a different width. */

.beyond p {
  font-size: var(--size-track-bullet);
  line-height: 1.7;
  color: var(--linework);
}

.beyond a {
  color: var(--accent-spiritual);
  font-size: 15px;
  font-weight: var(--weight-semi);
  text-decoration: underline;
  text-underline-offset: 3px;
}


/* ------------------------------------------------------------
   FAQ Block — Accordion                 (Tier 2 pages, Offerings)
   Threshold rule from A3: more than 3 questions -> Accordion,
   3 or fewer -> Flat. Native disclosure, one open by default.
   ------------------------------------------------------------ */

/* Width/positioning now comes from .text-col (paired in markup),
   same reasoning as .beyond above. */

.faq__item { border-bottom: 1px solid var(--border); }

.faq__item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-5) 0;
  min-height: 44px;
}

.faq__item summary::-webkit-details-marker { display: none; }

.faq__q {
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  line-height: var(--lh-h3);
  font-weight: var(--weight-semi);
}

.faq__sign {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  position: relative;
  margin-top: 4px;
}

.faq__sign::before,
.faq__sign::after {
  content: "";
  position: absolute;
  background: var(--accent);
  transition: transform 0.18s ease, opacity 0.18s ease;
}

.faq__sign::before { top: 9px; left: 2px; width: 16px; height: 2px; }
.faq__sign::after  { left: 9px; top: 2px; width: 2px; height: 16px; }

.faq__item[open] .faq__sign::after { transform: rotate(90deg); opacity: 0; }

.faq__a {
  padding-bottom: var(--space-5);
  font-size: var(--size-body);
  line-height: var(--lh-body);
}

/* Responsive. A1's locked rule across every component tested:
   stack vertically on mobile, always. The primer grid takes an
   intermediate two-across step, since four peer cards squeezed
   into a tablet width read as cramped rather than scannable. */
@media (max-width: 900px) {
  .primer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 768px) {
  .track-grid,
  .primer-grid { grid-template-columns: 1fr; }

  /* Stacked, so there is no adjacent card to align against and
     subgrid has nothing to do. Back to a simple flow. */
  .primer-grid { grid-template-rows: none; }
  .primer {
    display: block;
    grid-row: auto;
  }
}


/* ------------------------------------------------------------
   Sub-hero / "what I do" block                          (A3)

   The old rule resolved to --size-body at --lh-body, byte-identical
   to ordinary body copy: --size-body is 18px and Lead is 19px, so
   the claimed "step down from the hero's Lead" was one pixel and
   invisible. It needs to read as the hero's continuation rather
   than as the first paragraph of an unrelated section, so it gets
   a real mark: a rule at the rail plus the measure it deserves.
   ------------------------------------------------------------ */

/* A left accent rule was tried first and rejected at render: the
   rule plus its padding pushed the text 26px off the left rail,
   and one inset element on one page reads as a mistake, not a
   device. Colour does the same job without breaking the rail.
   Contrast checked: --linework on --tint is 4.94:1, clears AA. */
.subhero {
  max-width: var(--measure);
  color: var(--linework);
}

.subhero p {
  font-size: var(--size-body);
  line-height: var(--lh-body);
}


/* ------------------------------------------------------------
   CTA Pairing — asymmetric                              (A3)
   Solid accent button for the prominent action, plain underlined
   text link for the secondary. Never two competing buttons.
   Accent follows the page's own lens via --accent.
   ------------------------------------------------------------ */

.cta-pair {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
}

.cta-pair--center { justify-content: center; }

.btn {
  display: inline-block;
  background: var(--accent-text);
  color: var(--white);
  text-decoration: none;
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  letter-spacing: 0.01em;
  padding: var(--space-4) var(--space-6);
  border-radius: 6px;
  border: 1.5px solid var(--accent);
  /* 27 Aug, C01 + D2. Without this every button inherited body's 1.6,
     which is why .btn--lead rendered ~77px tall. Root cause, so the fix
     belongs here rather than on the variant. */
  line-height: 1.3;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.btn:hover { opacity: 0.88; }
.btn { transition: opacity var(--transition), background var(--transition), color var(--transition); }

/* Outlined variant — Working Session card, per Booking Cards */
.btn--outline {
  background: transparent;
  color: var(--accent-text);
}

.btn--outline:hover { background: var(--accent-text); color: var(--white); }

.btn--block { display: block; width: 100%; text-align: center; }

/* The diagnostic is Home's lead CTA and is spec'd as visually
   distinct and more inviting than the other two (GTM 3.6). */
.btn--lead {
  font-size: var(--size-body);
  /* 27 Aug, C01 + D2. Was --space-5 --space-7. Type size and shadow
     still mark this as the primary action; the padding was surplus. */
  padding: var(--space-4) var(--space-6);
  box-shadow: 0 4px 16px rgba(44, 82, 130, 0.22);
}

/* Genuinely inline link, sitting inside a run of prose (WCAG
   2.5.8's own inline exception — not a discrete control, so no
   44px minimum applies). Colour follows the page's own --accent,
   underlined like every other link, no layout changes to the
   surrounding paragraph. */
.inline-link {
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Standalone CTA links. These are not inline-in-prose links, so
   they carry the full 44px touch target rather than relying on
   the WCAG inline-text exemption. Padding is vertical only, so
   the underline still hugs the words. */
.link-secondary,
.link-cta {
  color: var(--accent-text);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.link-secondary {
  font-size: var(--size-caption);
  text-underline-offset: 3px;
}

.link-cta {
  font-size: var(--size-body);
  text-underline-offset: 4px;
}


/* ------------------------------------------------------------
   Testimonial Card                                      (A3)
   Left border follows the PAGE LENS, not a fixed sage. A3 named
   the sage hex directly, but hardcoding it meant Ganga Tattva's
   cards rendered inner-work green on the spiritual register page,
   which broke the colour continuity the Signpost bridge exists to
   create. One line to revert if the fixed sage is preferred.
   Quote 14px, name 13px/600, role 12px caption in linework.
   Card sizes to its own content; no fixed minimum height.
   ------------------------------------------------------------ */

/* 27 Aug, D5. --surface against --ground computes to 1.044:1, so the
   card had effectively no edge. Every sibling card component already
   carries a full border; this was the exception. C05 trims the side
   padding at the same time. */
.t-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--space-5);
}

.band--ground .t-card { box-shadow: 0 1px 3px rgba(35, 38, 43, 0.05); }

.t-card__quote {
  font-size: var(--size-quote);
  /* Italic per Arvind, 27 Aug: quote and attribution differed only by
     size and weight, so the card read as one undifferentiated block.
     Italic is already this site's marker for a subordinate voice, see
     .invest__note and polish-standard.md Section 9. */
  font-style: italic;
  line-height: 1.6;
  margin: 0;
}

.t-card__attrib { margin-top: var(--space-4); }

.t-card__name {
  font-size: var(--size-attrib-name);
  font-weight: var(--weight-semi);
  line-height: 1.4;
}

.t-card__role {
  display: inline;
  font-size: var(--size-attrib-role);
  line-height: var(--lh-caption);
  color: var(--linework);
}

/* The role is inline so the profile link can follow it, which means the
   block above needs to supply the gap the role's own margin used to. */
.t-card__name { margin-bottom: 2px; }

/* The LinkedIn mark is the one logged exception to the site-wide
   icons ban in polish-standard.md Section 7: a bare profile URL on
   a testimonial card is worse, and the glyph is universally read.
   No other icon enters through this door. Sized to the role line
   rather than the name, and carrying --linework until hover, so it
   sits as attribution rather than as a call to action. */
/* The profile link sits on the designation's line rather than claiming a
   row of its own: it is an adjunct to the attribution, not a third fact.
   .t-card__role is therefore inline, and the anchor flows after it. */
.t-card__in {
  display: inline-flex;
  align-items: center;
  margin-left: 0.5ch;
  vertical-align: -2px;
  color: var(--linework);
  transition: color .15s ease;
  position: relative;
}

/* The icon reads at 16px but is tapped at 28px. An absolutely positioned
   pseudo-element extends the hit area without touching the line box, so
   nothing reflows. Kept to 28px rather than 44px on purpose: reaching 44
   would overlap the name on the row above and send those taps to LinkedIn.
   WCAG 2.2 target-size exempts a control inline within a line of text,
   which is exactly what this now is. */
.t-card__in::after {
  content: "";
  position: absolute;
  inset: -6px;
}

.t-card__in:hover,
.t-card__in:focus-visible { color: var(--charcoal); }

.t-card__in-icon { display: block; }

/* Testimonial strip — the thin closing band used on Home and
   Ganga Tattva. Strips use Testimonial Card regardless of quote
   length: Ganga Tattva's map accepts a 26-word quote in a Card
   "for strip consistency, not an oversight," which settles the
   same question for Home's three sub-30-word quotes. */
.t-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  align-items: start;
}

.t-strip--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (max-width: 768px) {
  .t-strip, .t-strip--pair { grid-template-columns: 1fr; }
}

/* "View all testimonials ->" follows every testimonial band
   (GTM 3.3). Reachable only this way plus Home; never in nav. */
/* 27 Aug, C06. Was centred, which broke the rail rule under otherwise
   left-aligned cards. render-check only sees inline centring, so a
   class-based one escaped the harness entirely. */
.t-viewall {
  margin-top: var(--space-6);
  text-align: left;
}

.t-viewall a {
  color: var(--accent-text);
  font-size: var(--size-caption);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}


/* ------------------------------------------------------------
   REJECTED PATTERN, kept as a note so it is not re-proposed.

   A two-column hero with an "at a glance" aside (duration,
   format, nature) was built to fill the empty right rail beside
   program-page heroes, and rejected on sight.

   The standing rule: no program detail, meta block, spec list or
   price is ever placed beside a hero, on any page. The empty
   right rail is addressed through the length, size and
   description of the hero copy itself, and nothing else.
   ------------------------------------------------------------ */


/* ------------------------------------------------------------
   Structure & Investment panel

   The commercial terms were running as ordinary prose in an
   ordinary band, so the one place a reader goes looking for a
   number had no more visual weight than any other paragraph.
   A tinted panel makes it a distinct object. The add-on sits
   inside the same panel but visibly secondary, since it is an
   extension of the program rather than an alternative to it.
   ------------------------------------------------------------ */

.invest {
  /* One surface across the whole block. The add-on previously sat
     on --surface against main terms on --tint, which made the
     optional item read as the emphasised one. */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: var(--space-6);
  max-width: var(--measure);
}

.invest__main { padding: var(--space-6); }

.invest__amount {
  font-family: var(--font-heading);
  font-weight: var(--weight-semi);
  font-size: var(--size-h2);
  line-height: 1.1;
  color: var(--charcoal);
  margin-bottom: var(--space-5);
}

.invest__amount span {
  font-family: var(--font-body);
  font-size: var(--size-caption);
  font-weight: var(--weight-regular);
  color: var(--linework);
}

.invest__amount--sm {
  font-size: var(--size-h3);
  margin-bottom: var(--space-3);
}

.invest__spec {
  margin: 0;
  display: grid;
  gap: var(--space-3);
}

.invest__spec dt {
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-semi);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--linework);
}

.invest__spec dd {
  margin: 0;
  font-size: var(--size-body);
  line-height: 1.4;
}

.invest__addon {
  padding: var(--space-6);
  border-top: 1px solid var(--border);
}

/* Caught by render-check: at 13px this ran 88 characters a line
   inside the 640px panel. Measure is a character count, so the
   smaller the type the narrower the box has to be. */
.invest__addon p:last-child {
  font-size: var(--size-caption);
  line-height: var(--lh-caption);
  color: var(--linework);
  max-width: 30rem;
}

.invest__addon-label {
  font-size: var(--size-attrib-role);
  font-weight: var(--weight-semi);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--linework);
  margin-bottom: var(--space-2);
}

.invest__addon-label span {
  letter-spacing: 0;
  text-transform: none;
  font-weight: var(--weight-regular);
  font-style: italic;
}

@media (max-width: 1024px) {
  .hero-hook__inner { grid-template-columns: 1fr; gap: var(--space-6); }
  .hero-meta { max-width: var(--measure); }
}


/* Eligibility and therapy-boundary note. Ran at full body weight
   directly beneath the price and competed with it. It qualifies
   the offer rather than making it, so it takes footnote weight:
   smaller, italic, --linework. */
.invest__note {
  font-size: var(--size-caption);
  line-height: var(--lh-caption);
  font-style: italic;
  color: var(--linework);

  /* Deliberately --measure, not the 30rem small-text cap: this is
     a footnote to the panel above and has to share its right edge
     to read as part of the same object. Trades a slightly long
     line for the visual relationship. */
  max-width: var(--measure);
}


/* Prerequisite routing note (Inner Awareness Intensive).
   Deliberately NOT .invest__note weight. That class is for text
   qualifying the offer, which a reader can skim; this tells them
   to go somewhere else first, which they cannot afford to miss.
   It sits above the panel at body size with an accent rule. */
.prereq {
  border-left: 2px solid var(--accent);
  padding-left: var(--space-5);
  margin-bottom: var(--space-6);
  max-width: var(--measure);
}


/* What the program guarantees. Body weight, deliberately NOT
   .invest__note: this is the most persuasive content in the
   section and it was shipping in the smallest, greyest type on
   the page. Kept as prose rather than a bullet list, because
   three of the four program pages already carry this guardrail as
   prose and "You leave this stage with" is the Tier 2 stage-card
   device. */
.invest__guarantee {
  max-width: var(--measure);
  margin-bottom: var(--space-5);
}


/* Five-step arc (Transition). Four steps fit 720px; five at that
   width leaves columns too narrow for the longest label to hold
   one line, and the standard is to widen or shorten rather than
   pad with a min-height. This one widens to the rail. */
.arc--5 { max-width: 100%; }

/* An add-on whose price is held for live conversation. Kept at
   the same position and weight as a number so the row does not
   read as a blank where the others have figures. */
.invest__amount--quiet {
  font-family: var(--font-body);
  font-size: var(--size-body);
  font-style: italic;
  font-weight: var(--weight-regular);
  color: var(--linework);
}
/* ------------------------------------------------------------
   Loop Diagram — Inner Foundations Tier 2      (add to the Loop
   block in components.css, after .loop__node--fill)

   WHY THIS IS AN SVG AND NOT THE .loop FLEX CHAIN

   The old markup rendered five pills with forward arrows and
   nothing coming back, under a heading calling it a loop. The
   return is not decoration: the experience you end up with is
   what you bring to the next interpretation, and that IS the
   mechanism the program teaches, so the diagram has to close.

   A border-drawn connector was tried first and could only
   terminate at the row's outer edge, which put the arrowhead
   under Event. That is the wrong node. Events happen to you;
   experience cannot cause the next one, it changes how you read
   it. Landing the arrowhead on Interpretation's centre needs
   known coordinates, which means SVG.

   innerawarenessdetails renders its seven-node chain
   as SVG too (.loop-svg--deep), so the flexbox .loop-deep and
   .loop-deep__return rules this note once pointed at are gone.
   .loop itself stays in the codebase: innercompass renders it.

   ONE PILL WIDTH FOR ALL FIVE
   Nodes were first sized to their own text, which produced five
   different widths and read as accidental rather than composed,
   worst in the stacked variant where they sit in a column and
   the ragged right edge is unmissable. All five now take the
   width set by the longest label: "Interpretation" measures 80px
   at 13px IBM Plex Serif 600, plus 24px each side, so 128. Any
   future rename longer than "Interpretation" resets this number
   for every node, and the gap recalculates from it.

   TWO VARIANTS, NOT ONE SCALING VIEWBOX
   A single 912-wide viewBox scaled to a 390px viewport renders
   13px node text at about 5.5px. The stacked variant carries the
   same geometry vertically and swaps at the site's 768 breakpoint.
   ------------------------------------------------------------ */

.loop-svg { display: block; width: 100%; height: auto; }
.loop-svg--wide  { max-width: var(--rail); }
.loop-svg--stack { display: none; max-width: 230px; }

@media (max-width: 768px) {
  .loop-svg--wide  { display: none; }
  .loop-svg--stack { display: block; }
}

/* Non-text graphics need 3:1 under SC 1.4.11, which
   --accent-inner clears on every surface here, so the A1 hue
   holds. Node text sits on --surface or on the accent fill, both
   re-derived in tokens.css and passing. */
.loop-svg__pill          { fill: var(--surface); stroke: var(--accent-inner); stroke-width: 1.5; }
.loop-svg__pill--fill    { fill: var(--accent-inner); stroke: var(--accent-inner); }

.loop-svg__node          { font-family: var(--font-heading); font-size: 13px; font-weight: var(--weight-semi); fill: var(--charcoal); }
.loop-svg__node--on-fill { fill: var(--surface); }

/* 1.5 to 2, a third heavier. At 1.5 the connectors read lighter than
   the node borders they join, so the flow sat behind the nodes rather
   than driving them. */
.loop-svg__flow          { fill: none; stroke: var(--accent-inner); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* The Reinforcement return on the deep loop carries a gradient from
   the page accent into charcoal, so the one line that is feedback
   rather than sequence is distinguishable at a glance from the five
   arrows and the turn bracket that are. Sage and charcoal are both
   existing tokens: introducing a fourth hue here would break the lens
   system, since ochre and career blue each already mean something
   else. Darkening toward the destination rather than lightening away
   from the source is deliberate. This line is the page's own claim,
   so it should not read as the quiet one. */
.loop-svg__return        { fill: none; stroke: url(#deepReturn); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.loop-svg__grad-from     { stop-color: var(--accent-inner); }
.loop-svg__grad-to       { stop-color: var(--charcoal); }

/* Knocks the return label out of the rule it sits on. Tied to
   --tint because every Tier 2 loop band is tinted. If this is
   ever placed on a Ground band, this has to follow the band
   rather than stay hardcoded. */
.loop-svg__knock         { fill: var(--tint); }
.loop-svg__note          { font-family: var(--font-body); font-size: 12px; font-style: italic; fill: var(--accent-inner-text); }

/* .loop__caption was already in use on innercompass; it was
   unused on the Tier 2 pages until now. .loop itself also stays:
   innercompass renders it. The orphaned intervention-points rule
   was deleted, as were the orphaned deep-loop flexbox rules. */

/* Inner Awareness' deep loop is a serpentine: the top row runs left to
   right, the sequence turns at the right edge, and the bottom row runs
   back leftward, so the whole circuit reads clockwise. Two consequences
   worth writing down.

   First, the sequence turn is a small bracket just outside the right ink
   edge rather than a full-width connector between the rows. The earlier
   version ran both rows left to right, which forced the wrap to travel
   the entire width backwards, and that long line competed with the
   Reinforcement return for attention. Serpentine removes the competition
   structurally rather than by restyling one of the two.

   Second, the channel between the rows is now free, so the return runs
   through it and crosses nothing.

   The gap was tightened from 128.67 to 68, matching Inner Foundations,
   which means the diagram no longer spans the full rail. Deliberate: a
   tighter chain reads as one flow, and the two Tier 2 diagrams now share
   a rhythm. The viewBox is sized to the ink so it still renders 1:1. */
.loop-svg--deep { max-width: 790px; }


/* ------------------------------------------------------------
   Reference List — area names          (Traction Intensive Tier 2)

   The six area names shipped as .eyebrow: 12px uppercase, sitting
   above a .refitem__lead set at --size-h3 in the heading serif.
   The label was therefore a third the size of the sentence
   explaining it, which is the same inverted hierarchy
   polish-standard.md §3.2 catches in the heroes.

   The names are the content of this band, not a kicker on it, so
   they take --size-h3 and become real h3 elements, matching the
   stage-card names they sit alongside in the Tier 2 set. The lead
   drops to body and stops competing.
   ------------------------------------------------------------ */

.refitem__name { margin-bottom: var(--space-3); }

/* Overrides the component rule above, which set this at h3 scale
   in the heading serif back when it was the largest thing in the
   item. */
.refitem__lead {
  font-family: var(--font-body);
  font-size: var(--size-body);
  line-height: var(--lh-body);
  font-weight: var(--weight-regular);
}


/* ------------------------------------------------------------
   Ganga Tattva                                    (page-specific)

   TWO SOLID BUTTONS, DELIBERATELY
   Every other page carries one solid button, because a second one
   makes the reader choose before they have decided anything. Ganga
   is the exception: a free community and a paid session are
   parallel doors, not a primary and a fallback, and
   ganga-tattva-planning-checklist.md locks them at equal visual
   weight with no colour-treatment distinction. render-check.mjs
   needs this page on an allowlist for that assertion rather than
   the page quietly failing it.

   The pair is left at the rail like everything else. .cta-pair-sym
   centres its contents, which is why the old markup needed an
   inline text-align to begin with.
   ------------------------------------------------------------ */

.ganga-cta {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-top: var(--space-7);
}
.ganga-cta .btn { flex: 0 1 240px; text-align: center; }

.ganga-hero__copy { margin-top: var(--space-6); }
.ganga-hero__copy > p + p { margin-top: var(--space-5); }

/* Both hero slots share one ratio so the boxes match. Change the
   custom property to 16/9 when the video replaces the portrait. */
.ganga-fig {
  margin: 0;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--tint);
}

.ganga-fig > img,
.ganga-fig > svg { display: block; width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 768px) {
}

/* Line art rather than photography or a generated image.
   polish-standard.md §8 rules out stock imagery on the grounds it
   costs trust with a skeptical reader, and a photoreal generated
   image sits in the same family. Ochre linework on parchment is
   the register this page already uses, and it cannot date. */
/* The line-art CSS that lived here is gone. The tree ships as an
   external file with its colour baked in, so site CSS cannot reach
   inside it and .ganga-art, .riv__* and .tr__* addressed nothing.
   Inline the SVG again and they come back with it. */

/* ------------------------------------------------------------
   GANGA TATTVA, 27 August rebuild.

   The page moved to the five-section structure in
   docs/canon/page-copy-master.md section 10: the roots claim leads,
   water gets its own band, and the tree illustration sits in the
   hero rather than one band down.

   .ganga-fig--bare exists because the artwork is transparent line
   art. The framed .ganga-fig paints --tint behind it and draws a
   border, which was invisible while the figure sat in a Tint band
   and reads as a hard-edged darker panel now that it sits in a
   Ground one.
   ------------------------------------------------------------ */

.ganga-eyebrow {
  font-size: var(--size-caption);
  font-weight: var(--weight-semi);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: var(--space-4);
}

.ganga-hero__split { margin-top: var(--space-7); }
.ganga-hero__split .ganga-hero__copy { margin-top: 0; }

.ganga-lead {
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  font-weight: var(--weight-semi);
}

.ganga-sub {
  font-family: var(--font-heading);
  font-weight: var(--weight-regular);
  font-size: var(--size-h3);
  line-height: var(--lh-h3);
  margin-top: var(--space-7);
  margin-bottom: var(--space-5);
}

.ganga-questions {
  font-family: var(--font-heading);
  font-size: var(--size-h3);
  line-height: 1.55;
  max-width: var(--measure);
  color: var(--accent-text);
  margin-top: var(--space-6);
}

.ganga-note {
  font-size: var(--size-caption);
  line-height: var(--lh-caption);
  font-style: italic;
  color: var(--linework);
  max-width: 30rem;
  margin-top: var(--space-6);
}

.ganga-jump {
  display: inline-block;
  margin-top: var(--space-6);
  font-weight: var(--weight-semi);
}

.ganga-fig--bare {
  border: 0;
  background: none;
  border-radius: 0;
  /* Square box, art scaled to fill it. The drawing is 4:3, so the
     sides crop by ~12% each and the ground line runs out of frame,
     which reads as a drawn line rather than a clipped picture. */
  aspect-ratio: 1 / 1;
  align-self: center;
}
.ganga-fig--bare > img {
  object-fit: cover;
  object-position: 50% 50%;
  width: 100%;
  height: 100%;
}

/* ------------------------------------------------------------
   Mobile density, 27 August visual review C02, C08 + D10, C09.
   Large panels kept desktop internal padding at 390px, where the
   same 32px is a far larger share of the card. 16px per Arvind.
   ------------------------------------------------------------ */
@media (max-width: 768px) {
  /* C02. Home leads with the message; My Story deliberately does not,
     so this is opt-in by modifier rather than a change to the base. */
  .hero-felt__portrait--after-copy { order: initial; }

  .stage__head,
  .stage__body,
  .invest__main,
  .invest__addon { padding: var(--space-4); }

  .faq__item summary { padding: var(--space-4) 0; }
  .faq__a { padding-bottom: var(--space-4); }
}

/* ------------------------------------------------------------
   Round 3, 27 August. Marquee testimonial, and the Offerings CTA.
   ------------------------------------------------------------ */

/* 1b. The 46ch cap kept a display-size line readable but left a hard
   band of whitespace beside the marquee quote. */
.pullquote--feature { max-width: var(--measure); }

/* 1c. Role and LinkedIn mark share a line instead of stacking, and the
   block sits closer to the cards it introduces. */
.pullquote-attrib { margin-bottom: var(--space-5); }
.pullquote-attrib__role { display: inline; }
.pullquote-attrib__in { margin-top: 0; margin-left: var(--space-2); vertical-align: middle; }

/* Item 7. Filter bar and the grid under it. */
.filter-bar { padding-block: var(--space-3); }
.filter-bar__inner { padding-bottom: var(--space-3); }
.t-grid { margin-top: var(--space-5); }

/* Item 6. Solid Explore buttons. Branch-coloured rather than uniformly
   blue, because these two cards already carry the inner-work lens in
   their top border and canon scopes lens accents to exactly this: CTA
   tint, diagram accents, borders, badges. The label is white on both;
   the pre-existing .primer--inner colour rule is more specific than a
   plain .primer__cta a, which is why it has to be named here.
   The harness allows four solid buttons because it counts distinct
   labels and all four read 'Explore'. */
.primer__cta a {
  display: inline-block;
  min-height: auto;
  padding: var(--space-3) var(--space-5);
  border-radius: 6px;
  text-decoration: none;
  font-weight: var(--weight-semi);
  font-size: var(--size-caption);
  line-height: 1.3;
  text-align: center;
  background: var(--accent-career);
  border: 1.5px solid var(--accent-career);
  color: var(--white);
}
.primer--inner .primer__cta a {
  background: var(--accent-inner);
  border-color: var(--accent-inner);
  color: var(--white);
}

/* The duration line sat 72px above the button: 48px of grid row space
   plus 24px of padding inside the CTA box. Now 24px. */
.primer__cta { padding-top: 0; }
.primer-grid { row-gap: var(--space-2); }
.primer__duration { margin-bottom: 0; }
