/* ==========================================================================
   IKV Finservices — Mobile and tablet corrections
   --------------------------------------------------------------------------
   LOADED LAST. Every rule in this file lives inside a
   `@media (max-width: 1099.98px)` block or narrower, so the desktop layout at
   1100px and above is byte-for-byte unaffected by this file. Nothing here
   overrides a desktop value; it only supplies values the shared sheets do not
   have for small screens, or corrects values that are wrong at small
   screens.

   Each section notes the file and line it corrects, so a rule here can be
   folded back into its owner once that owner grows a mobile story of its own.
   ========================================================================== */


/* ==========================================================================
   1. Tokens
   --------------------------------------------------------------------------
   The shared sheet floors --gutter at 1.75rem (28px), which costs a 320px
   phone 17.5% of its width on each side, and pairs --sticky-offset (114px)
   with a --header-h of 88px even though the utility bar sits on top of that
   88px, so the real header is ~128px and every anchored jump under-reserves
   by roughly 14px. Both are corrected here for small screens only.
   ========================================================================== */

@media (max-width: 767.98px) {
  :root {
    --gutter: clamp(1rem, 0.55rem + 1.7vw, 1.75rem);

    /* Real measured values: utility bar + the shorter nav row below. */
    --header-h: 72px;
    --utility-h: 40px;
    --sticky-offset: 112px;

    /* Vertical rhythm: the shared scale starts at 3.5rem (56px), which is
       a lot of dead air on a 640px-tall phone. */
    --section-y: clamp(2.5rem, 1.8rem + 4vw, 4rem);
    --section-y-sm: clamp(2rem, 1.5rem + 3vw, 3rem);

    /* Legal and assumption copy is --fs-xs (13px). At that size it is the
       least legible text on the page and it is the copy that matters most,
       so the floor rises by half a point on phones only. */
    --fs-xs: 0.84375rem;
  }
}

/* Very small phones: 320px and below (iPhone SE 1st gen, Galaxy Fold when
   closed, small Androids). The gutter tightens further so the measure
   stays around 35-40 characters rather than dropping into the low 30s. */
@media (max-width: 359.98px) {
  :root {
    --gutter: 0.875rem;
  }
}

/* --------------------------------------------------------------------------
   1a. Long headings
   `text-wrap: balance` is set on every heading in global.css. Balance splits
   a heading into even lines, which on a narrow column turns a two-line
   heading into three short ones with an orphaned word. Below 480px the
   column is short enough that `pretty` (which only avoids orphans) reads
   better.
   -------------------------------------------------------------------------- */
@media (max-width: 479.98px) {
  h1, h2, h3, h4, h5, h6 {
    text-wrap: pretty;
  }
}


/* ==========================================================================
   2. Header and brand
   --------------------------------------------------------------------------
   components.css:267 sizes the logo with `height: 64px; width: auto`. The
   source file is 6940x1356 (aspect 5.12), so the "260px" logo is actually
   rendered 328px wide, and at the 48px mobile height it is still 246px.
   Measured at 320px that produced a document 347px wide with the menu
   toggle pushed half off-screen.

   `.brand` also carries `flex-shrink: 0`, so it could never give ground.
   The logo is now bounded by both height and width, and the gaps shrink.
   ========================================================================== */

@media (max-width: 1099.98px) {
  .site-header__inner {
    gap: var(--sp-3);
    min-width: 0;
  }

  .brand {
    min-width: 0;
  }

  .brand img {
    height: clamp(38px, 9vw, 60px);
    width: auto;
    max-width: 100%;
  }

  .site-header__actions {
    flex: none;
  }

  /* The mobile panel is a fixed overlay inside the header's stacking
     context. It pads its own top by --header-h, which on mobile is only
     the nav row — the utility bar sits above it, so the first link would
     land under the header. Pad by the real combined offset instead. */
  .site-nav {
    padding-top: calc(var(--sticky-offset) + var(--sp-4));
  }
}


/* --------------------------------------------------------------------------
   2a. The close button has to sit above the open panel

   `.site-nav` becomes `position: fixed; inset: 0; z-index: var(--z-mobile-nav)`
   (1000) below 1100px, while `.nav-toggle` has no z-index. Both live inside
   `.site-header`, which carries `z-index: var(--z-header)` (900) and
   therefore forms the stacking context they share. A positioned element with
   z-index 1000 paints above every z-index:auto sibling, so the full-bleed
   white panel covered the entire header row.

   Confirmed by measurement: with the panel open, the menu button was not
   hittable — Playwright's actionability check timed out on it, and the only
   ways out were a link tap or the Escape key, which a phone does not have.

   Raising the brand and the action cluster above the panel restores both the
   logo and a tappable close button. Both elements are static on desktop, so
   this cannot affect the 1100px-and-up layout.
   -------------------------------------------------------------------------- */
@media (max-width: 1099.98px) {
  .site-header__inner > .brand,
  .site-header__actions {
    position: relative;
    z-index: calc(var(--z-mobile-nav) + 1);
  }

  /* The logo sits on the panel's white ground rather than the page's, so it
     keeps its own surface and cannot show the links scrolling underneath. */
  .site-header__inner > .brand {
    background: #fff;
    padding-right: var(--sp-3);
  }
}

/* ==========================================================================
   3. Buttons and stacked action rows
   --------------------------------------------------------------------------
   `.hero__actions` pairs "Explore Investment Solutions" with "Speak to Our
   Team". The first is ~263px wide including its padding, which is the entire
   content width of a 320px screen, so the row either overflows or leaves an
   orphaned button on line two. Below 480px each button takes the full width.
   ========================================================================== */

@media (max-width: 479.98px) {
  .hero__actions,
  .hero__actions > .btn,
  .d-flex.flex-wrap.gap-3 > .btn {
    width: 100%;
  }

  .hero__actions > .btn,
  .d-flex.flex-wrap.gap-3 > .btn {
    flex: 1 1 100%;
  }

  /* The flex gap still applies between wrapped rows, so nothing collides. */
  .hero__actions,
  .d-flex.flex-wrap.gap-3 {
    gap: var(--sp-3) !important;
  }
}

/* The single centred button under a section (`.mt-4 > .btn`) is fine full
   width too, but only where it is the sole child. */
@media (max-width: 479.98px) {
  .mt-4 > .btn:only-child,
  .mt-5 > .btn:only-child {
    width: 100%;
  }
}


/* ==========================================================================
   4. Form controls
   --------------------------------------------------------------------------
   components.css:838 sizes `.form-control` and `.form-select` at --fs-sm
   (15px). iOS and iPadOS Safari zoom the whole viewport on focus for any
   input under 16px and never zoom back out, so a visitor who taps the
   contact form is stranded at ~1.25x until they reload. Measured: 14
   controls under 16px at a 320px viewport.

   The threshold is the operating system's, not the layout's, so this covers
   the whole tablet range too — a 15px field on a 1024px iPad zooms exactly
   as it does on a phone. Raised to 1rem below 1100px; desktop is untouched.

   The ten calculator panels build their number inputs at runtime in
   calculators.js, so they are covered by the `.calc .form-control` selector
   rather than by any markup change.
   ========================================================================== */

@media (max-width: 1099.98px) {
  .form-control,
  .form-select,
  .faq-search input,
  .calc .form-control,
  input[type="text"],
  input[type="tel"],
  input[type="email"],
  input[type="number"],
  input[type="search"],
  input[type="url"],
  input[type="password"],
  select,
  textarea {
    font-size: 1rem;
  }
}

/* The number spinners eat horizontal room in a narrow field. */
@media (max-width: 479.98px) {
  .calc .form-control[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
  }
  .calc .form-control[type="number"]::-webkit-outer-spin-button,
  .calc .form-control[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
}


/* ==========================================================================
   5. Calculator
   ========================================================================== */

/* --------------------------------------------------------------------------
   5a. Tab strip
   components.css:969 wraps the ten tabs. On a phone that is three ragged
   rows and the active tab is often off screen. Below 768px the strip
   becomes a single horizontally scrollable, snap-aligned row instead. The
   arrow-key handling in calculators.js is untouched and still works; it
   additionally scrolls the newly selected tab into view.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .calc-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Bleed to the card edge so a partially scrolled tab reads as scrollable
       rather than as cut-off text. */
    margin-inline: calc(-1 * var(--sp-3));
    padding-inline: var(--sp-3);
    padding-bottom: 2px;
  }

  .calc-tabs::-webkit-scrollbar {
    display: none;
  }

  .calc-tab {
    flex: 0 0 auto;
    scroll-snap-align: center;
    white-space: nowrap;
  }
}

/* --------------------------------------------------------------------------
   5b. Result rows
   Measured at 320px the result column is 169px wide. `.calc__row` is a flex
   row with a label and a value, so both shrink and wrap: "Monthly need at
   retirement" renders as a four-line label beside a two-line right-aligned
   value, and the two no longer share a baseline. There is no room for two
   columns at this width, so below 576px the pair becomes a stacked
   definition — label above, value below — which is what the dt/dd markup
   already says it is.
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .calc__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-1);
    align-items: start;
  }

  .calc__row dt {
    font-size: var(--fs-xs);
    line-height: 1.45;
  }

  .calc__row dd {
    text-align: left;
    font-size: var(--fs-sm);
    overflow-wrap: anywhere;
  }

  /* The primary figure carries the whole answer; give it room to break a
     long rupee amount rather than running it into the panel edge. */
  .calc__primary {
    overflow-wrap: anywhere;
  }
}

/* Below 576px the two calculator columns have already stacked
   (components.css:1007). Reduce the card padding so the value column keeps
   a usable measure. */
@media (max-width: 575.98px) {
  .calc {
    padding: var(--sp-4);
  }

  .calc__result {
    padding: var(--sp-4);
  }
}


/* ==========================================================================
   6. Touch targets
   --------------------------------------------------------------------------
   Audit at 320px found 58 interactive elements below the 44px minimum
   recommended target size. The offenders and their measured heights:
     .hero-marquee__group a ............. 27px  (13 links)
     .link-arrow ....................... 27px
     .footer__list a .................. 16-21px
     .footer__legal a ................. 16px
     .utility-bar a ................... 16px
     .dropdown__link .................. 40px
   They are enlarged below. Widths are left alone — these are inline text
   links and forcing a width would distort the reading rhythm.
   ========================================================================== */

@media (max-width: 1099.98px) {
  /* Hero marquee: 13 links scroll past continuously under a thumb.
     Measured 27px before, 45px after. */
  .hero-marquee__group a {
    padding-block: 0.75rem;
  }

  /* Inline arrow links in section body copy. 27px -> 44px. */
  .link-arrow {
    padding-block: 0.625rem;
  }

  /* The two phone numbers on the contact cards are the primary action in
     that section, and they were the smallest targets on the page at 21px.
     Each sits on its own line under an uppercase label, so the padding
     costs no neighbouring line. 21px -> 44px. */
  .contact-card__value a {
    display: inline-block;
    padding-block: 0.5rem;
    min-height: 44px;
  }

  /* Footer link columns. 16-21px -> 44px. */
  .footer__list a {
    display: inline-block;
    padding-block: 0.4rem;
    min-height: 44px;
  }

  /* Footer columns - center align on mobile */
  .footer__col {
    align-items: center;
    text-align: center;
  }
  .footer__list {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .footer__contact {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .footer__contact li {
    justify-content: center;
  }
  .footer__logo {
    margin-left: auto;
    margin-right: auto;
  }

  /* Footer contact numbers sit inside a flex row with a 16px icon, so the
     padding has to clear the icon box too. */
  .footer__contact a {
    display: inline-block;
    padding-block: 0.4rem;
    min-height: 44px;
  }

  .footer__legal a {
    display: inline-block;
    padding-block: 0.4rem;
    min-height: 40px;
  }

  /* FAQ sidebar links. */
  .faq-aside__list a {
    padding-block: 0.75rem;
  }

  /* Mobile sub-navigation. */
  .dropdown__link {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding-block: 0.5rem;
  }

  /* The home link is 195px wide at this breakpoint, so only its height was
     short. */
  .brand {
    min-height: 44px;
  }

  /* Consent checkbox. WCAG 2.5.8 (Target Size, Minimum) asks for 24x24; the
     shared sheet ships 20x20. The whole row is labelled and tappable, but
     the box itself is what people aim at. */
  .checkbox-field input[type="checkbox"] {
    width: 24px;
    height: 24px;
  }

  /* Keep the error message aligned under the label text now that the box
     has grown (components.css:895 offsets by the old 20px width). */
  .checkbox-field .field__error {
    margin-left: calc(24px + var(--sp-3));
  }
}

/* The footer list gap was carrying the spacing between rows; with padding
   inside each link it would double up. Pull it back on touch layouts. */
@media (max-width: 1099.98px) {
  .footer__list li {
    margin-bottom: 0;
  }
}

/* Utility bar phone number — the one number a phone visitor taps first.
   Raising it to 44px makes the utility bar taller than --utility-h, so the
   header grows. Rather than chase the height with another token edit, the
   ResizeObserver in navigation.js measures the real header and rewrites
   --sticky-offset, which keeps the anchored-scroll offset exact at every
   width without any further CSS bookkeeping. */
@media (max-width: 1099.98px) {
  .utility-bar__list a {
    display: inline-block;
    padding-block: 0.4rem;
    min-height: 44px;
  }
}


/* ==========================================================================
   7. Grid tracks
   --------------------------------------------------------------------------
   Several shared grids declare `1fr` rather than `minmax(0, 1fr)`. A `1fr`
   track is floored at its content's min-content width, so a long unbroken
   word inside one column can push the row wider than the container. The
   container is `.overflow-x: hidden`, which hides the symptom rather than
   the cause. These are scoped to small screens so desktop track sizing is
   untouched.
   ========================================================================== */

@media (max-width: 991.98px) {
  .atlas-support {
    grid-template-columns: minmax(0, 1fr);
  }
}

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

  .calc-directory {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

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

@media (max-width: 575.98px) {
  .values,
  .calc-directory,
  .scheme-list,
  .related,
  .compare-3,
  .contact-cards {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* ==========================================================================
   8. Component corrections
   ========================================================================== */

/* --------------------------------------------------------------------------
   8a. Principles list
   pages.css:277 lays each row out as `auto 1fr`, and `.principles__key`
   carries `min-width: 92px` on top of that. The key is uppercase at
   --fs-xs with 0.16em tracking, so "CONTINUITY" alone measures ~105px and
   the value column is left with whatever remains. Below 576px the key sits
   on its own line and the value takes the full width.
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .principles li {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-2);
  }

  .principles__key {
    min-width: 0;
  }
}

/* --------------------------------------------------------------------------
   8b. Timeline bands
   pages.css:543 only collapses these to one column below 575.98px. Between
   576px and 768px the label column is still pinned at up to 220px, which
   leaves the bar under 300px and squeezes the label and its note into a
   narrow ribbon. Stack them across the whole tablet range.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .timeline-band {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-2);
    align-items: stretch;
  }

  .timeline-band__bar {
    height: 32px;
  }
}

/* --------------------------------------------------------------------------
   8c. Accordion panel
   components.css:793 reserves a fixed 3rem on the right to clear the
   chevron. That is 48px of a 264px column on a 320px phone. The chevron is
   now cleared by the panel padding on the right only where there is room.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .accordion__panel-inner {
    padding-right: 0;
  }
}

/* --------------------------------------------------------------------------
   8d. Risk bars and notices
   -------------------------------------------------------------------------- */
@media (max-width: 479.98px) {
  .notice,
  .risk-note {
    padding: var(--sp-4);
  }

  .stat {
    padding-left: var(--sp-3);
  }
}

/* --------------------------------------------------------------------------
   8e. Trust strip
   components.css:648 runs a 28px icon beside the copy. Below 480px the
   stack is stacked outright so the title and description start at the same
   left edge as the section heading.
   -------------------------------------------------------------------------- */
@media (max-width: 479.98px) {
  .trust-item {
    flex-direction: column;
    gap: var(--sp-2);
  }
}

/* --------------------------------------------------------------------------
   8f. Bento cells
   pages.css:352 collapses the bento grid to one 230px row on phones. The
   pill and the two-line description do not fit that height at the widths
   involved, so give the row a little more room.
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .landscape-bento {
    grid-auto-rows: 250px;
  }

  .bento-cell,
  .bento-cell.tall {
    min-height: 250px;
  }

  .bento-cell__body {
    padding: var(--sp-3) var(--sp-4);
  }
}

/* --------------------------------------------------------------------------
   8g. About card
   accents.css:698 already stacks the floating card below 575.98px. The
   frame above it keeps the shared 4:3 ratio, which on a phone is taller
   than the copy beside it needs.
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .about-media__frame {
    aspect-ratio: 3 / 2;
  }
}

/* --------------------------------------------------------------------------
   8h. Footer
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .footer__legal {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-3);
  }
}

/* --------------------------------------------------------------------------
   8i. Leader / person blocks
   pages.css:717 already stacks the leader below 768px. The portrait is
   capped at 220px, which on a 320px phone leaves it looking oversized next
   to the biography. Trim it.
   -------------------------------------------------------------------------- */
@media (max-width: 479.98px) {
  .leader__photo {
    max-width: 160px;
  }

  .person__photo {
    width: 88px;
  }
}


/* --------------------------------------------------------------------------
   8j. Bootstrap `g-5` negative margins

   `.g-5` sets a 3rem gutter, which Bootstrap implements as a 1.5rem negative
   margin on each side of the row. That only sits inside the container when
   the container padding is at least 1.5rem. The shared --gutter floors at
   1.75rem, so it always did — but the mobile gutter floor above is 1rem, and
   measured across 280px to 767px the "Why IKV Finservices" and final CTA rows
   were sticking out of the viewport by 5px to 10px on each side.

   `g-4` (a 0.75rem negative margin) still fits, so only `g-5` is reduced,
   and only below 768px. At 768px and up the shared gutter applies and this
   rule does not match.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .row.g-5 {
    --bs-gutter-x: 1.5rem;
  }
}


/* ==========================================================================
   9. Tables
   --------------------------------------------------------------------------
   `.table-scroll` carries horizontal scrolling, but `.table-compare thead
   th` is `white-space: nowrap` and the first column is pinned at 24%. On a
   phone that leaves very little for the body columns. Below 576px the cell
   padding is trimmed so more of the value fits per screen.
   ========================================================================== */

@media (max-width: 575.98px) {
  .table-compare th,
  .table-compare td {
    padding: var(--sp-3);
  }

  .table-compare tbody th {
    width: 32%;
  }
}


/* ==========================================================================
   11. Hero photograph
   --------------------------------------------------------------------------
   pages.css:13 paints `hero.png` — a 1679x937 PNG weighing 2.38 MB — behind
   the whole first screen, and `hero-1280.jpg` (61 KB) / `hero-2560.jpg`
   (177 KB) sit unused in the same folder. On a phone that one file is most
   of the page weight before anything else is requested.

   A first attempt used `image-set()` with `w` descriptors. `CSS.supports()`
   reports false for that in current Chromium (and it is unreliable across
   engines generally), so the fallback fired and the full-size PNG loaded on
   every device regardless — verified by request log, not assumed. The
   photograph is therefore a real <picture> element in the markup, which
   every engine handles.

   Below 1100px the photo becomes that element, sized by the browser from
   viewport width and device pixel ratio, with the dark gradient moved onto
   `::after` so it still sits over the image. The gradient values are copied
   verbatim from pages.css, so contrast over the photograph is unchanged.

   At 1100px and up `.hero__bg` is display:none: no layout box, no request,
   and the hero paints hero.png from CSS exactly as it always has.
   ========================================================================== */

@media (min-width: 1100px) {
  .hero__bg {
    display: none;
  }
}

@media (max-width: 1099.98px) {
  .hero {
    /* Solid navy underneath, so the gradient reads over the photo the same
       way it read over the PNG. */
    background-color: var(--c-navy);
    background-image: none;
  }

  .hero__bg {
    display: block;
    position: absolute;
    inset: 0;
    z-index: -1;
    overflow: hidden;
  }

  .hero__bg img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
  }

  .hero__bg::after {
    content: "";
    position: absolute;
    inset: 0;
    /* Desktop scrims the photo horizontally (90deg): the copy sits in a
       narrow left column, over the dark end of the gradient. On a phone the
       copy spans the full width, so every line reaches into the transparent
       70% band and crosses the bright part of the photograph — measured
       white-on-sunset at roughly 1.8:1, well under the 4.5:1 needed for body
       copy, and worst on the lead paragraph and the two buttons.

       Below 768px the scrim therefore runs vertically and stays opaque
       enough for text across the whole width. The photograph still reads
       through it, and the desktop gradient above is untouched. */
    background-image: linear-gradient(180deg,
      rgba(7, 29, 73, 0.86) 0%,
      rgba(7, 29, 73, 0.78) 38%,
      rgba(7, 29, 73, 0.74) 68%,
      rgba(7, 29, 73, 0.86) 100%);
  }
}


/* ==========================================================================
   12. Reduced data
   --------------------------------------------------------------------------
   A visitor on a metered or deliberately throttled connection gets the small
   hero variant only. The gradient still carries the copy, so legibility is
   unaffected.
   ========================================================================== */

@media (prefers-reduced-data: reduce) {
  .hero__bg img {
    content: url("../images/rwd/hero_mobile-480w.jpg");
  }
}

/* The element is only ever visible below 1100px (see section 11). On wider
   viewports the sources do not match and the <img> holds a 1x1 transparent
   pixel, so nothing is painted and nothing is requested. This rule states
   that intent explicitly rather than leaving it implicit in the markup. */
@media (min-width: 1100px) {
  .hero__bg {
    display: none;
  }
}


/* ==========================================================================
   13. Centred content on phones
   --------------------------------------------------------------------------
   Phones only. Every rule in this section sits inside
   `@media (max-width: 767.98px)`; 768px and above is untouched, and the
   tablet range keeps its left-aligned layout.

   `text-align` inherits, so setting it once on the two content roots covers
   headings, leads, body copy, list items, card copy, notices, stat labels,
   definition lists, accordion panels, calculator labels, form labels and
   footer copy in a single declaration. What follows is the small set of
   components that either set their own `text-align` or lay out with flex,
   and so need to be named explicitly to follow.

   Two deliberate exclusions:

     - The value inside an input, select or textarea stays left-aligned.
       Centred numerals make the digits shift sideways as a figure is being
       typed, which is worse to read than a left-aligned field, and the
       calculator asks for ten-digit rupee amounts.
     - The header row is not included. The logo sits left and the menu button
       right by design; centring them is a navigation change, not a content
       alignment one.
   ========================================================================== */

@media (max-width: 767.98px) {
  main,
  .footer {
    text-align: center;
  }

  /* --- Components that declare their own alignment --------------------- */

  .accordion__trigger {
    text-align: center;
  }

  .table-compare th,
  .table-compare td,
  .table-compare caption {
    text-align: center;
  }

  /* Result rows stacked at 576px keep the same treatment as the copy. */
  .calc__row dd {
    text-align: center;
  }

  /* --- Flex and grid rows that centre themselves via distribution ----- */

  .eyebrow--accented,
  .page-hero .eyebrow,
  .cat-hero .eyebrow,
  .cta-final .eyebrow,
  .global-visual .eyebrow {
    justify-content: center;
  }

  .hero__meta,
  .breadcrumb,
  .footer__legal {
    justify-content: center;
    align-items: center;
    text-align: center;
  }

  /* --- Centring the box, not just the text ------------------------------ */

  /* `text-align: center` only centres text INSIDE its own box. A block that
     carries a max-width is narrower than its column, and with no
     `margin-inline: auto` that narrower box stays pinned to the left edge —
     so the centred text inside it sits visibly off to one side.

     accents.css and pages.css set max-width on a number of headings and
     leads purely to control line length on wide screens (22ch-30ch on the
     section h2s, 46ch-56ch on the leads, 30ch on the SIP stat labels, 52ch
     on the mutual-funds definition list, 34ch on the footer description).
     Those constraints are still correct on a phone — they keep the measure
     readable — but the box itself now has to be centred too.

     Measured before this rule, the worst offsets were:
       .stat__label ("One scheduled amount, set once") ....  95px left
       h2 ("Built for every goal. Backed by research.") .. 130px left
       .footer__brand-desc ................................  201px left
       dd ("Units of a scheme, not the company's shares") . 106px left
       .lead ("A Systematic Investment Plan invests...") ..  55px left

     `margin-inline: auto` is a no-op on a block that already fills its
     column, so this is safe to apply to block-level text generally rather
     than naming each width-constrained element. */
  main :is(h1, h2, h3, h4, h5, h6, p, dd, dt, blockquote, figcaption),
  .footer :is(h1, h2, h3, h4, h5, h6, p, dd, dt, blockquote, figcaption) {
    margin-inline: auto;
  }

  /* The rule above is specificity (0,0,2), and `.definition-list dd` in
     components.css uses the `margin` shorthand (`margin: 4px 0 0`), which
     resets margin-inline to 0 at (0,1,1) and therefore wins. That left the
     three mutual-funds definitions pinned to the left of a 52ch box between
     600px and 768px, where that max-width starts to bind. Restated here at
     (0,1,2) so the box centres with the rest. */
  main .definition-list :is(dt, dd),
  .footer .definition-list :is(dt, dd) {
    margin-inline: auto;
  }

  /* --- Form fields ------------------------------------------------------ */

  .form-control,
  .form-select,
  textarea.form-control,
  .faq-search input {
    text-align: left;
  }

  .checkbox-field label {
    text-align: center;
  }

  /* --- Lists that reserve space on the left for a marker -------------- */

  /* The diamond and tick markers stay on the left edge so the list still
     reads as a list; only the text centres. */
  .check-list li {
    padding-left: 1.75rem;
    text-align: center;
  }

  .trust-item {
    text-align: center;
  }

  .trust-item > div {
    text-align: center;
  }

  /* --- Images and decorative rules ------------------------------------- */

  /* An image or rule is not text, so it does not follow `text-align`. The
     footer logo and the gold accent rules would otherwise sit hard against
     the left gutter while the copy around them is centred. */
  .footer__logo {
    margin-inline: auto;
  }

  .rule-gold,
  .rule-gold-soft,
  .rule-green-soft {
    margin-inline: auto;
  }

  /* --- Rows that carry a leading icon ---------------------------------- */

  .contact-cards .contact-card__title {
    justify-content: center;
  }

  /* --- Hero meta line ---------------------------------------------------- */

  /* The separator dot is drawn on every span but the last, so once the two
     items wrap onto separate lines it is left dangling at the end of the
     first. Stacked lines need no separator, so the dot is dropped and the
     gap carries the spacing instead. */
  @media (max-width: 479.98px) {
    .hero__meta {
      flex-direction: column;
      gap: var(--sp-1);
    }

    .hero__meta span::after {
      content: none;
    }
  }
}


/* ==========================================================================
   14. Hero rotating word
   --------------------------------------------------------------------------
   `.hero__rot` (pages.css) is an inline-grid whose single shared cell is
   always as wide as the widest word, so that swapping words never reflows or
   re-wraps the headline. That is deliberate and is kept.

   The cost is dead space. Measured at 320px, 390px and 430px:

       Investment ....... 180px cell / 180px text .....  0px slack
       Finance .......... 180px cell / 123px text ..... 57px slack
       Wealth ........... 180px cell / 111px text ..... 69px slack

   Because the cell stays inline it shares a line with "Multiple" on one side
   and "Opportunities." on the other, so on a phone that slack reads as a gap
   punched into the middle of the headline - and it shifts by 12px between
   words as the animation runs.

   Below 768px the rotator becomes a full-width block, so it takes a line of
   its own. The cell is still sized to the widest word, so a swap still
   changes no layout at all; only the slack moves from a gap between words to
   ordinary centring padding on its own line, where it is invisible.
   "Multiple" and "Opportunities." then read as clean separate lines instead
   of being split around a hole.

   The reduced-motion rule in pages.css switches `.hero__rot` to
   `display: inline`; this rule is later in the cascade and wins at equal
   specificity, so the single pinned word still sits on its own line.
   ========================================================================== */

@media (max-width: 767.98px) {
  .hero__rot {
    /* `grid`, not `inline-grid` and emphatically not `block`. The words must
       keep sharing one cell (grid-template-areas: "slot", inherited from
       pages.css) or they stop overlapping and stack as three lines — which
       makes the headline jump on every swap, the very thing the shared cell
       exists to prevent. Only the outer display level changes: block-level
       grid instead of inline-level, so the rotator takes a full-width line of
       its own and the reserved width is no longer a gap between words. */
    display: grid;
    width: 100%;
    margin: 0;
  }

  /* Each word fills the cell and centres within it, so whichever word is
     active sits dead centre regardless of its own width. */
  .hero__rot__word {
    justify-self: stretch;
    text-align: center;
  }
}


/* ==========================================================================
   Note for whoever picks this up next
   --------------------------------------------------------------------------
   Desktop (1100px and up) is deliberately untouched by this entire file.
   Two known wins are left on the table there, both available as one-line
   changes if the desktop layout is ever opened for review:

     1. pages.css:13 still paints hero.png (2.38 MB) rather than the WebP
        image-set above. Identical pixels, ~13x less data.
     2. The utility bar, footer and carousel-adjacent imagery have no
        srcset because they are text and CSS, but any future desktop image
        should follow the <picture> pattern already used in index.html.
   ========================================================================== */