/* ==========================================================================
   CostGuard – Public pages, shared vocabulary
   ──────────────────────────────────────────────────────────────────────────
   The section vocabulary every redesigned public page is built from. Sits on
   top of /css/costguard-theme.css and consumes its --cg-* semantic tokens, so
   both themes and any future brand change flow through automatically.

   Load order in App.razor — AFTER the child theme, BEFORE any page stylesheet:
     1. /themes/canvas/style.css
     2. /themes/canvas/css/font-icons.css
     3. /themes/canvas/css/custom.css
     4. /css/costguard-theme.css
     5. /css/costguard-public.css      ← THIS FILE
     6. /css/costguard-home.css, /css/costguard-product.css, …

   How a page opts in:
     #wrapper.cg-pub-wrapper           the backdrop behind the top of the page
     section#content.cg-pub            the scope; its .content-wrap owns the gap
     section.cg-pub / .cg-pub-band     one per section, direct children of
                                       .content-wrap, carrying no padding of
                                       their own

   No colour literals below: every value resolves through --cg-*.

   The shapes a page alternates, so that no two neighbours look alike:
     centred statement                 .cg-pub-center
     centred hero                      .cg-pub-center.cg-pub-hero-center
     quiet columns under a hairline    .cg-pub-columns / .cg-pub-feature
     split row under a hairline        .cg-pub-split (+ .cg-pub-chips)
     one large product frame           .cg-pub-frame
     full-bleed band, sticky editorial .cg-pub-band / .cg-sticky-col / .cg-pub-ledger
     numbered steps                    .cg-pub-steps
     figures                           .cg-pub-stats
     bento grid                        .cg-pub-bento
     long document, sticky contents    .cg-pub-doc (+ -intro, -toc, -body, -section,
                                       -note, -meta, -related, -hero, -contact)
     closing statement on ink          .cg-pub-promo (+ .cg-pub-promo-center)
   Product previews are built from .cg-mock*. Page-only shapes (the home hero,
   for instance) live in that page's own stylesheet.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Local aliases — one place to retune the home page without touching tokens
   -------------------------------------------------------------------------- */

.cg-pub {
    --cg-pub-panel-bg:     var(--cg-bg-elevated);
    --cg-pub-panel-border: var(--cg-border);
    --cg-pub-band-bg:      var(--cg-bg-subtle);
    --cg-pub-ink:          var(--cg-text-primary);
    --cg-pub-muted:        var(--cg-text-secondary);
    --cg-pub-track:        var(--cg-border);
    --cg-pub-bar:          color-mix(in srgb, var(--cg-accent-text) 30%, transparent);
    --cg-pub-radius:       0.875rem;
    --cg-pub-radius-lg:    1.25rem;
    --cg-pub-radius-xl:    1.75rem;

    /* The only vertical gap on the page. It breathes a little with the
       viewport, because display-size headlines need more air than 64px on a
       wide screen, but it is still one value at every boundary. */
    --cg-pub-gap:          clamp(4rem, 6vw, 5.5rem);

    /* Inner spacing scale — 12, 16, 24 and 32px. */
    --cg-pub-space-1:      0.75rem;
    --cg-pub-space-2:      1rem;
    --cg-pub-space-3:      1.5rem;
    --cg-pub-space-4:      2rem;
}

/* --------------------------------------------------------------------------
   Page backdrop

   A soft accent glow and a dot grid behind the top of the page. It lives on
   the wrapper rather than on the hero so that it also runs underneath the
   header, which is transparent until the page scrolls.
   -------------------------------------------------------------------------- */

.cg-pub-wrapper {
    isolation: isolate;
}

.cg-pub-wrapper::before,
.cg-pub-wrapper::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 60rem;
    z-index: -1;
    pointer-events: none;
}

.cg-pub-wrapper::before {
    background:
        radial-gradient(46rem 28rem at 50% -4rem, var(--cg-accent-glow), transparent 72%),
        radial-gradient(28rem 20rem at 88% 6rem, var(--cg-accent-soft), transparent 70%);
}

.cg-pub-wrapper::after {
    background-image: radial-gradient(var(--cg-border-strong) 1px, transparent 1px);
    background-size: 1.75rem 1.75rem;
    -webkit-mask-image: radial-gradient(60rem 30rem at 50% 0, black, transparent 72%);
    mask-image: radial-gradient(60rem 30rem at 50% 0, black, transparent 72%);
    opacity: 0.7;
}

.cg-pub-wrapper #content {
    background: transparent;
}

/* --------------------------------------------------------------------------
   Section rhythm

   One value, --cg-pub-gap, sets every vertical gap on the page: above the
   first section, between any two sections, and below the last one before the
   footer links. The sections themselves carry no vertical padding, so no
   boundary can double up. A banded section uses the same value as its own
   inner padding, so its background breathes by exactly that amount too.
   -------------------------------------------------------------------------- */

.cg-pub > .content-wrap {
    padding-top: var(--cg-pub-gap);
    padding-bottom: var(--cg-pub-gap);
}

/* Bootstrap's vertical gutter pulls the row up by --bs-gutter-y and pads every
   column back down by the same amount. On a row that is the first thing inside
   a section that negative margin silently eats the section's top spacing. Side
   by side from lg up, the vertical gutter buys nothing, so it is switched off
   there; below lg the columns stack and it is what separates them. */
@media (min-width: 992px) {
    .cg-pub .row.g-5 {
        --bs-gutter-y: 0;
    }
}

.cg-pub > .content-wrap > section.cg-pub {
    padding-block: 0;
    margin-block: 0;
}

.cg-pub > .content-wrap > .cg-pub-band {
    margin-block: 0;
    padding-block: var(--cg-pub-gap);
}

/* These three selectors all outrank the two rules above, which zero the
   margins — a plain `> * + *` rule does not, and was silently dropped. */
.cg-pub > .content-wrap > section.cg-pub + section.cg-pub,
.cg-pub > .content-wrap > section.cg-pub + .cg-pub-band,
.cg-pub > .content-wrap > .cg-pub-band + section.cg-pub {
    margin-top: var(--cg-pub-gap);
}

/* --------------------------------------------------------------------------
   Type

   Headlines take the display face; everything else stays on the text face the
   theme assigns at the root. Sizes are fluid, so there is one scale instead of
   a breakpoint ladder.
   -------------------------------------------------------------------------- */

.cg-pub .cg-pub-display {
    margin: 0;
    font-family: var(--cg-font-display);
    font-weight: var(--cg-display-weight);
    letter-spacing: var(--cg-display-tracking);
    line-height: 1.04;
    color: var(--cg-pub-ink);
    text-wrap: balance;
}

.cg-pub .cg-pub-display-xl {
    font-size: clamp(2.75rem, 1.35rem + 5.4vw, 5.5rem);
    line-height: 0.98;
}

.cg-pub .cg-pub-display-lg {
    font-size: clamp(2.125rem, 1.45rem + 2.5vw, 3.5rem);
}

.cg-pub .cg-pub-display-md {
    font-size: clamp(1.5rem, 1.3rem + 0.8vw, 1.875rem);
    line-height: 1.12;
}

/* Arabic-script and Han headlines need room for their ascenders, marks and
   full-height glyphs; the Latin leading clips them. */
html[lang="fa"] .cg-pub .cg-pub-display,
html[lang="ar"] .cg-pub .cg-pub-display,
html[lang="zh"] .cg-pub .cg-pub-display {
    line-height: 1.3;
}

.cg-pub .cg-pub-heading {
    max-width: 20ch;
    margin-bottom: 3rem;
}

.cg-pub-eyebrow {
    margin-bottom: var(--cg-pub-space-2);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--cg-accent-text);
}

html[lang="fa"] .cg-pub-eyebrow,
html[lang="ar"] .cg-pub-eyebrow {
    letter-spacing: 0;
}

.cg-pub .cg-pub-lead {
    max-width: 40rem;
    margin: 0;
    font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.3125rem);
    line-height: 1.55;
    color: var(--cg-pub-muted);
}

.cg-pub .cg-pub-title {
    margin: 0 0 0.5rem;
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--cg-pub-ink);
}

.cg-pub .cg-pub-body {
    margin: 0;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--cg-pub-muted);
}

.cg-pub-center .cg-pub-eyebrow,
.cg-pub-center .cg-pub-heading {
    margin-inline: auto;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Centred hero — the page title as a centred statement, no box
   -------------------------------------------------------------------------- */

.cg-pub-hero-center {
    text-align: center;
}

.cg-pub .cg-pub-hero-center .cg-pub-display-xl {
    max-width: 16ch;
    margin-inline: auto;
    margin-bottom: var(--cg-pub-space-4);
    font-size: clamp(2.5rem, 1.6rem + 3.6vw, 4.75rem);
    line-height: 1.02;
}

html[lang="fa"] .cg-pub .cg-pub-hero-center .cg-pub-display-xl,
html[lang="ar"] .cg-pub .cg-pub-hero-center .cg-pub-display-xl,
html[lang="zh"] .cg-pub .cg-pub-hero-center .cg-pub-display-xl {
    line-height: 1.3;
}

.cg-pub .cg-pub-hero-center .cg-pub-lead {
    max-width: 44rem;
    margin-inline: auto;
    margin-bottom: var(--cg-pub-space-4);
}

/* --------------------------------------------------------------------------
   Shared primitives
   -------------------------------------------------------------------------- */

/* Icons are sized to the type beside them and sit in one tinted tile. */
.cg-pub-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    margin-bottom: 1.25rem;
    border-radius: 0.75rem;
    background: var(--cg-accent-soft);
    color: var(--cg-accent-text);
    font-size: 1.125rem;
    line-height: 1;
}

.cg-pub-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cg-pub-space-2) var(--cg-pub-space-3);
}

.cg-pub-band {
    background: var(--cg-pub-band-bg);
}

.cg-pub-panel {
    background: var(--cg-pub-panel-bg);
    border: 1px solid var(--cg-pub-panel-border);
    border-radius: var(--cg-pub-radius);
    box-shadow: var(--cg-shadow-sm);
}

.cg-pub-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    border: 1px solid var(--cg-border);
    border-radius: 50rem;
    padding: 0.3rem 0.75rem;
    font-size: 0.75rem;
    color: var(--cg-pub-muted);
}

/* The announcement badge: a tinted tag inside a quiet pill, not a filled
   button-blue lozenge. */
.cg-pub-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: var(--cg-pub-space-4);
    padding-block: 0.3125rem;
    padding-inline: 0.3125rem 0.875rem;
    border: 1px solid var(--cg-border);
    border-radius: 50rem;
    background: var(--cg-bg-elevated);
    box-shadow: var(--cg-shadow-sm);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--cg-pub-muted);
}

.cg-pub-badge-tag {
    padding: 0.1875rem 0.5625rem;
    border-radius: 50rem;
    background: var(--cg-accent-soft);
    color: var(--cg-accent-text);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
}

.cg-pub-proof {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 1.75rem;
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.875rem;
    color: var(--cg-pub-muted);
}

.cg-pub-proof li {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.cg-pub-proof i {
    color: var(--cg-accent-text);
    font-size: 1rem;
    line-height: 1;
}

/* --------------------------------------------------------------------------
   Product frame — one large preview in a window frame
   -------------------------------------------------------------------------- */

.cg-pub-frame {
    width: 100%;
    max-width: 68rem;
    margin-top: calc(var(--cg-pub-gap) * 0.75);
    border: 1px solid var(--cg-pub-panel-border);
    border-radius: var(--cg-pub-radius-lg);
    background: var(--cg-pub-panel-bg);
    color: var(--cg-pub-ink);
    box-shadow: var(--cg-shadow-lg), 0 3rem 8rem -3rem var(--cg-accent-glow);
    overflow: hidden;
}

.cg-pub-frame-bar {
    display: flex;
    align-items: center;
    gap: var(--cg-pub-space-2);
    padding: var(--cg-pub-space-1) var(--cg-pub-space-3);
    border-bottom: 1px solid var(--cg-border);
    background: var(--cg-bg-subtle);
}

.cg-pub-frame-dots {
    display: inline-flex;
    gap: 0.375rem;
}

.cg-pub-frame-dots span {
    width: 0.625rem;
    height: 0.625rem;
    border-radius: 50%;
    background: var(--cg-border-strong);
}

.cg-pub-frame-bar .cg-mock-sub {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cg-pub-frame-bar .cg-pub-frame-period {
    flex: 0 0 auto;
    margin-inline-start: auto;
}

.cg-pub-frame-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cg-pub-space-3);
    padding: var(--cg-pub-space-3);
}

.cg-pub-frame-side {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr));
    gap: var(--cg-pub-space-1);
}

@media (min-width: 768px) {
    .cg-pub-frame-body {
        grid-template-columns: minmax(0, 1fr) 17rem;
        padding: var(--cg-pub-space-4);
        gap: var(--cg-pub-space-4);
    }

    .cg-pub-frame-side {
        grid-template-columns: minmax(0, 1fr);
        grid-auto-rows: 1fr;
    }

    .cg-pub-frame-side > .cg-mock-tile {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }
}

/* --------------------------------------------------------------------------
   Product mockups — pure markup previews of real CostGuard screens
   -------------------------------------------------------------------------- */

.cg-mock {
    background: var(--cg-pub-panel-bg);
    border: 1px solid var(--cg-pub-panel-border);
    border-radius: var(--cg-pub-radius);
    padding: var(--cg-pub-space-3);
    color: var(--cg-pub-ink);
}

/* The dashboard preview is a section's single object, so it gets the larger
   radius and the long shadow the hero frame carries. */
.cg-mock-stage {
    border-radius: var(--cg-pub-radius-lg);
    box-shadow: var(--cg-shadow-lg);
    text-align: start;
}

@media (min-width: 768px) {
    .cg-mock-stage {
        padding: var(--cg-pub-space-4);
    }
}

.cg-mock-title {
    font-size: 0.875rem;
    font-weight: 600;
    margin-bottom: 0.15rem;
}

.cg-mock-sub {
    font-size: 0.78rem;
    color: var(--cg-pub-muted);
}

.cg-mock-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--cg-pub-muted);
    margin-bottom: 0.5rem;
}

html[lang="fa"] .cg-mock-label,
html[lang="ar"] .cg-mock-label {
    letter-spacing: 0;
}

.cg-mock-value {
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.cg-mock-value-xl {
    font-size: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem);
    letter-spacing: -0.035em;
    line-height: 1;
}

.cg-mock-value-sm {
    font-size: 0.88rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Spend going up is a risk signal, so it takes the risk colour. */
.cg-mock-delta {
    font-size: 0.875rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cg-warning);
}

.cg-mock-status {
    flex: 0 0 auto;
    padding: 0.2rem 0.6rem;
    border-radius: 50rem;
    background: color-mix(in srgb, var(--cg-success) 14%, transparent);
    color: var(--cg-success);
    font-size: 0.6875rem;
    font-weight: 600;
}

.cg-mock-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
    gap: var(--cg-pub-space-1);
}

.cg-mock-tile {
    background: var(--cg-bg);
    border: 1px solid var(--cg-border);
    border-radius: 0.75rem;
    padding: var(--cg-pub-space-2) 1.125rem;
}

.cg-mock-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1.25rem;
    background: var(--cg-accent-soft);
    border: 1px solid color-mix(in srgb, var(--cg-accent-text) 35%, transparent);
    border-radius: 0.75rem;
    padding: var(--cg-pub-space-1) 1.125rem;
}

.cg-mock-action .cg-mock-label {
    color: var(--cg-accent-text);
    margin-bottom: 0;
}

/* A cost increase a recommendation found is a risk signal, not money saved, so it takes the risk colour. */
.cg-mock-increase {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cg-warning);
}

/* Bar chart ---------------------------------------------------------------- */

.cg-mock-bars {
    display: flex;
    align-items: flex-end;
    gap: 0.2rem;
    height: 7rem;
}

/* A chart inside a stretched tile takes the spare height rather than leaving
   a gap above the summary strip. */
.cg-mock-tile.d-flex > .cg-mock-bars {
    flex: 1 1 auto;
    min-height: 7rem;
}

.cg-mock-bars-lg {
    height: clamp(8rem, 5rem + 9vw, 12.5rem);
    gap: clamp(0.125rem, 0.4vw, 0.3125rem);
}

.cg-mock-bar {
    flex: 1 1 0;
    min-width: 0;
    background: var(--cg-pub-bar);
    border-radius: 3px 3px 0 0;
}

.cg-mock-bar.is-current {
    background: var(--cg-accent);
}

.cg-mock-bar.is-forecast {
    background: var(--cg-accent-soft);
    border: 1px dashed var(--cg-accent-text);
    border-bottom: 0;
}

.cg-mock-axis {
    display: flex;
    justify-content: space-between;
    font-size: 0.6875rem;
    color: var(--cg-pub-muted);
    margin-top: 0.5rem;
}

/* Donut -------------------------------------------------------------------- */

.cg-mock-donut {
    position: relative;
    width: 8.25rem;
    height: 8.25rem;
    border-radius: 50%;
    background: conic-gradient(var(--cg-chart-1) 0 37%,
                               var(--cg-chart-2) 37% 59%,
                               var(--cg-chart-3) 59% 73%,
                               var(--cg-chart-4) 73% 84%,
                               var(--cg-chart-6) 84% 93%,
                               var(--cg-chart-8) 93% 100%);
}

.cg-mock-donut-hole {
    position: absolute;
    inset: 1.6rem;
    border-radius: 50%;
    background: var(--cg-pub-panel-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.cg-mock-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    min-width: 0;
}

.cg-mock-legend li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.78rem;
}

.cg-mock-legend .cg-swatch {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 2px;
    flex: 0 0 auto;
}

.cg-mock-legend .cg-name {
    color: var(--cg-pub-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cg-mock-legend .cg-share {
    margin-inline-start: auto;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Progress rows ------------------------------------------------------------ */

.cg-mock-rows {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.cg-mock-row-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.35rem;
    font-size: 0.78rem;
}

.cg-mock-row-head .cg-amount {
    color: var(--cg-pub-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cg-mock-track {
    height: 0.375rem;
    border-radius: 3px;
    background: var(--cg-pub-track);
    overflow: hidden;
}

.cg-mock-fill {
    height: 100%;
    border-radius: 3px;
    background: var(--cg-accent);
}

.cg-mock-fill.is-warning {
    background: var(--cg-warning);
}

.cg-mock-row-head .cg-amount.is-warning {
    color: var(--cg-warning);
}

/* Ranked list -------------------------------------------------------------- */

.cg-mock-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cg-mock-list li {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 0;
    border-top: 1px solid var(--cg-border);
}

.cg-mock-list .cg-text {
    font-size: 0.78rem;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Each row's amount is the cost increase its check found: risk, not a saving. */
.cg-mock-list .cg-amount {
    margin-inline-start: auto;
    font-size: 0.78rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cg-warning);
    white-space: nowrap;
}

.cg-impact {
    flex: 0 0 auto;
    border-radius: 0.3rem;
    padding: 0.1rem 0.45rem;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    border: 1px solid var(--cg-border-strong);
    color: var(--cg-pub-muted);
}

.cg-impact.is-high {
    border-color: var(--cg-warning);
    color: var(--cg-warning);
}

/* Summary strip ------------------------------------------------------------ */

.cg-mock-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 5.5rem), 1fr));
    gap: 0.75rem;
    border-top: 1px solid var(--cg-border);
    padding-top: 0.75rem;
    margin-top: 0.9rem;
}

/* --------------------------------------------------------------------------
   Features — three quiet columns. No boxes: a hairline, an icon, a title and
   a sentence, and whitespace does the rest.
   -------------------------------------------------------------------------- */

.cg-pub-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: 2.5rem 3rem;
}

.cg-pub-feature {
    padding-top: var(--cg-pub-space-3);
    border-top: 1px solid var(--cg-border-strong);
}

/* --------------------------------------------------------------------------
   Split — a heading on one side and its prose, or a chip list, on the
   other, under a single hairline
   -------------------------------------------------------------------------- */

.cg-pub-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cg-pub-space-4) 4rem;
    padding-top: var(--cg-pub-space-4);
    border-top: 1px solid var(--cg-border-strong);
}

@media (min-width: 992px) {
    .cg-pub-split {
        grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    }
}

.cg-pub-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cg-pub-space-1);
    list-style: none;
    margin: var(--cg-pub-space-4) 0 0;
    padding: 0;
}

.cg-pub-chips > .cg-pub-chip {
    padding: 0.5rem 1rem;
    background: var(--cg-bg-elevated);
    font-size: 0.875rem;
    color: var(--cg-pub-ink);
}

.cg-pub-chips i {
    color: var(--cg-accent-text);
    font-size: 1rem;
    line-height: 1;
}

/* --------------------------------------------------------------------------
   Dashboard — four figures under the product frame. Amber marks risk (an
   alert, a cost increase); no figure is money saved, so none is green.
   -------------------------------------------------------------------------- */

.cg-pub-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
    gap: var(--cg-pub-space-4) 3rem;
    margin-top: 3rem;
}

.cg-pub-stats > div {
    padding-inline-start: 1.25rem;
    border-inline-start: 1px solid var(--cg-border-strong);
}

.cg-pub-stat {
    margin-bottom: 0.5rem;
    font-family: var(--cg-font-display);
    font-weight: var(--cg-display-weight);
    font-size: clamp(2.25rem, 1.7rem + 1.8vw, 3.25rem);
    line-height: 1;
    letter-spacing: var(--cg-display-tracking);
    font-variant-numeric: lining-nums;
    color: var(--cg-pub-ink);
}

.cg-pub-stat.is-risk {
    color: var(--cg-warning);
}

/* --------------------------------------------------------------------------
   Why — editorial two-column in a full-bleed band, then numbered steps
   -------------------------------------------------------------------------- */

/* Canvas clips .section, and a clipped ancestor is a scroll container as far
   as position: sticky is concerned, so the band has to let it through. */
@media (min-width: 992px) {
    .cg-pub > .content-wrap > .cg-pub-band {
        overflow: visible;
    }

    .cg-pub .cg-sticky-col {
        position: sticky;
        top: 7rem;
    }
}

.cg-pub-ledger {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cg-pub-ledger > li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 1.25rem;
    padding-block: var(--cg-pub-space-3);
    border-top: 1px solid var(--cg-border-strong);
}

.cg-pub-ledger > li:last-child {
    border-bottom: 1px solid var(--cg-border-strong);
}

.cg-pub-ledger .cg-pub-icon {
    margin-bottom: 0;
}

.cg-pub-steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 2.5rem 3rem;
    margin: var(--cg-pub-gap) 0 0;
    padding: 0;
    list-style: none;
    counter-reset: cg-pub-step;
}

.cg-pub-step {
    counter-increment: cg-pub-step;
}

.cg-pub-step::before {
    content: counter(cg-pub-step, decimal-leading-zero);
    display: block;
    margin-bottom: var(--cg-pub-space-2);
    font-family: var(--cg-font-display);
    font-weight: var(--cg-display-weight);
    font-size: 2.75rem;
    line-height: 1;
    font-variant-numeric: lining-nums;
    color: var(--cg-accent-text);
}

/* --------------------------------------------------------------------------
   Bento — a grid of previews: one wide split card and any number of cards
   -------------------------------------------------------------------------- */

/* Two explicit columns from md up. auto-fit produced a third track on wide
   screens that the two cards could not fill, and squeezed each card narrow
   enough that its title wrapped. */
.cg-pub-bento {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cg-pub-space-3);
}

@media (min-width: 768px) {
    .cg-pub-bento {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.cg-pub-bento-copy {
    padding: var(--cg-pub-space-4) var(--cg-pub-space-4) 0;
}

.cg-pub-bento > .cg-pub-bento-wide {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
    align-items: center;
    background:
        radial-gradient(34rem 20rem at 100% 0, var(--cg-accent-glow), transparent 70%),
        var(--cg-pub-band-bg);
    border: 1px solid var(--cg-pub-panel-border);
    border-radius: var(--cg-pub-radius-xl);
    overflow: hidden;
}

.cg-pub-bento-wide > .cg-pub-bento-copy {
    padding-bottom: var(--cg-pub-space-4);
}

.cg-pub .cg-pub-bento-wide .cg-pub-display-md {
    font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.5rem);
}

.cg-pub-bento-wide-mount {
    padding: var(--cg-pub-space-4);
}

.cg-pub-bento-wide-mount > .cg-mock {
    box-shadow: var(--cg-shadow-md);
}

.cg-pub-bento-card {
    display: flex;
    flex-direction: column;
    background: var(--cg-pub-panel-bg);
    border: 1px solid var(--cg-pub-panel-border);
    border-radius: var(--cg-pub-radius-xl);
    overflow: hidden;
}

/* The mount grows to fill whatever height the taller sibling sets, and the
   preview grows with it. margin-top: auto pinned the preview to the card's
   bottom instead, which left a dead gap under the card's text. */
.cg-pub-bento-card > .cg-mock-mount {
    flex: 1 1 auto;
    display: flex;
    padding: var(--cg-pub-space-3) var(--cg-pub-space-4) var(--cg-pub-space-4);
}

.cg-pub-bento-card > .cg-mock-mount > .cg-mock {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--cg-bg);
}

/* When the sibling card is taller, the rows spread through the spare height
   instead of leaving it empty under the last one. */
.cg-pub-bento-card > .cg-mock-mount > .cg-mock > .cg-mock-rows {
    flex: 1 1 auto;
    justify-content: space-evenly;
}

/* --------------------------------------------------------------------------
   Document — a long text (a policy, terms, an overview) under a centred hero.

   Markup, inside ONE section.cg-pub that is a direct child of .content-wrap:
     .cg-pub-doc                 the grid
       .cg-pub-doc-intro         the lead and the note          (.cg-pub-doc-lead, .cg-pub-doc-note)
       nav.cg-pub-doc-toc.cg-sticky-rail   "on this page"       (.cg-pub-doc-toc-title, ul > li > a)
       .cg-pub-doc-body          section.cg-pub-doc-section per h2, then
                                 nav.cg-pub-doc-related, one quiet row of links
   The hero is .cg-pub-hero-center.cg-pub-doc-hero; the status and date lines
   under its title are .cg-pub-doc-meta. A contact section holds
   .cg-pub-doc-contact (its first line is .cg-pub-doc-contact-name).

   The DOM order is the reading order, so a narrow screen shows the lead, the
   note, the contents and then the text. From lg up the contents become a
   sticky rail on the inline-start side, spanning both rows. The section is a
   plain section.cg-pub — never canvas's .section, which clips its overflow
   and would make the rail stick to nothing. The rail's class carries
   "sticky-" so that it survives being given a col-* class one day.

   The contents are plain anchor links. There is no "current section"
   highlight: that needs an observer, and Blazor would drop its state when the
   circuit attaches. Headings that are link targets clear the fixed header
   through scroll-margin-top. No reveal either — a legal text is simply there.
   -------------------------------------------------------------------------- */

.cg-pub-doc {
    /* The measure is counted in the document's own type size, so the grid
       carries that size and the text inherits it. The zero of the text face
       is wide: 60ch sets 75 to 80 characters to the line, where 68ch set 86. */
    --cg-pub-doc-measure: 60ch;
    --cg-pub-doc-offset:  7rem;

    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--cg-pub-space-4);
    font-size: 1.0625rem;
}

.cg-pub-doc-intro,
.cg-pub-doc-body {
    max-width: var(--cg-pub-doc-measure);
}

@media (min-width: 992px) {
    .cg-pub-doc {
        grid-template-columns: minmax(0, 15rem) minmax(0, var(--cg-pub-doc-measure));
        grid-template-areas:
            "toc intro"
            "toc body";
        justify-content: center;
        column-gap: clamp(3rem, 6vw, 6rem);
        row-gap: 0;
    }

    .cg-pub-doc-intro {
        grid-area: intro;
    }

    .cg-pub-doc-body {
        grid-area: body;
    }

    .cg-pub-doc-toc {
        grid-area: toc;
        align-self: start;
        position: sticky;
        top: var(--cg-pub-doc-offset);
        max-height: calc(100vh - var(--cg-pub-doc-offset) - var(--cg-pub-space-4));
        overflow-y: auto;
    }
}

/* The hero of a document (.cg-pub-doc-hero beside .cg-pub-hero-center): the
   title is followed by short lines rather than a lead, so it sits closer to
   them than it would to a paragraph. */
.cg-pub .cg-pub-doc-hero .cg-pub-display-xl {
    margin-bottom: var(--cg-pub-space-3);
}

/* Status and date lines under the hero title. */
.cg-pub-doc-meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.25rem var(--cg-pub-space-3);
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
    color: var(--cg-pub-muted);
}

.cg-pub .cg-pub-doc-meta p {
    margin: 0;
}

.cg-pub .cg-pub-doc-lead {
    margin: 0;
    font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
    line-height: 1.6;
    color: var(--cg-pub-ink);
}

/* A note is information, not a risk, so it takes no amber: a quiet surface,
   a hairline and the accent in its text role on the icon. */
.cg-pub-doc-note {
    display: flex;
    align-items: flex-start;
    gap: var(--cg-pub-space-1);
    margin-top: var(--cg-pub-space-4);
    padding: var(--cg-pub-space-2) var(--cg-pub-space-3);
    border: 1px solid var(--cg-border);
    border-radius: var(--cg-pub-radius);
    background: var(--cg-pub-band-bg);
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--cg-pub-ink);
}

.cg-pub-doc-note > i {
    flex: 0 0 auto;
    font-size: 1.125rem;
    line-height: 1.35;
    color: var(--cg-accent-text);
}

/* Contents. The hairline is carried by each item rather than by the list, so
   it survives the list breaking into columns on a tablet. */
.cg-pub .cg-pub-doc-toc-title {
    margin: 0 0 var(--cg-pub-space-2);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--cg-pub-muted);
}

html[lang="fa"] .cg-pub .cg-pub-doc-toc-title,
html[lang="ar"] .cg-pub .cg-pub-doc-toc-title {
    letter-spacing: 0;
}

.cg-pub-doc-toc ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cg-pub-doc-toc li {
    border-inline-start: 1px solid var(--cg-border);
    break-inside: avoid;
}

.cg-pub .cg-pub-doc-toc a {
    display: block;
    margin-inline-start: -1px;
    padding-block: 0.375rem;
    padding-inline: var(--cg-pub-space-2) 0.25rem;
    border-inline-start: 1px solid transparent;
    font-size: 0.875rem;
    line-height: 1.4;
    color: var(--cg-pub-muted);
    text-decoration: none;
}

.cg-pub .cg-pub-doc-toc a:hover,
.cg-pub .cg-pub-doc-toc a:focus-visible {
    border-inline-start-color: var(--cg-accent-text);
    color: var(--cg-pub-ink);
}

/* The section being read, marked by /js/public-document.js on every document page:
   the help articles and the legal documents alike. */
.cg-pub .cg-pub-doc-toc a[aria-current="location"] {
    border-inline-start-color: var(--cg-accent-text);
    color: var(--cg-accent-text);
    font-weight: 600;
}

@media (min-width: 576px) and (max-width: 991.98px) {
    .cg-pub-doc-toc ul {
        columns: 2;
        column-gap: var(--cg-pub-space-4);
    }
}

/* Text. One hairline above every numbered section; its subsections are
   separated by whitespace alone. */
.cg-pub-doc-section {
    margin-top: var(--cg-pub-space-4);
    padding-top: var(--cg-pub-space-4);
    border-top: 1px solid var(--cg-border);
}

.cg-pub-doc-body [id] {
    scroll-margin-top: var(--cg-pub-doc-offset);
}

.cg-pub .cg-pub-doc-section > h2 {
    margin-bottom: var(--cg-pub-space-2);
}

.cg-pub .cg-pub-doc-section > h3 {
    margin-top: var(--cg-pub-space-4);
}

.cg-pub .cg-pub-doc-section > h2 + h3 {
    margin-top: var(--cg-pub-space-3);
}

.cg-pub .cg-pub-doc-section p {
    margin: 0 0 var(--cg-pub-space-2);
    line-height: 1.7;
    color: var(--cg-pub-ink);
}

.cg-pub .cg-pub-doc-section p:last-child {
    margin-bottom: 0;
}

.cg-pub .cg-pub-doc-section p a {
    overflow-wrap: anywhere;
    color: var(--cg-accent-text);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

.cg-pub .cg-pub-doc-section p a:hover {
    text-decoration-thickness: 2px;
}

/* Who to write to. The lines belong together, so they sit tighter than
   paragraphs, under the company name. */
.cg-pub-doc-contact {
    margin-bottom: var(--cg-pub-space-3);
    padding-inline-start: var(--cg-pub-space-3);
    border-inline-start: 1px solid var(--cg-border-strong);
}

.cg-pub .cg-pub-doc-contact p {
    margin-bottom: 0.25rem;
}

.cg-pub .cg-pub-doc-contact .cg-pub-doc-contact-name {
    font-weight: 600;
}

/* The way out of a document: one quiet row, not a closing panel. */
.cg-pub-doc-related {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cg-pub-space-1) var(--cg-pub-space-4);
    margin-top: var(--cg-pub-gap);
    padding-top: var(--cg-pub-space-3);
    border-top: 1px solid var(--cg-border-strong);
}

.cg-pub-doc-related-label {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--cg-pub-muted);
}

html[lang="fa"] .cg-pub-doc-related-label,
html[lang="ar"] .cg-pub-doc-related-label,
html[lang="zh"] .cg-pub-doc-related-label {
    letter-spacing: 0;
}

/* --------------------------------------------------------------------------
   Promo — the closing statement. On ink in both themes, so the page always
   ends on its darkest, quietest surface. The accent is re-pointed at its ink
   variant so the primary button keeps its presence against navy.
   -------------------------------------------------------------------------- */

.cg-pub-promo {
    --cg-accent:       var(--cg-ink-accent);
    --cg-accent-hover: var(--cg-ink-accent-hover);
    --cg-focus-ring:   var(--cg-ink-focus-ring);

    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
    align-items: end;
    background:
        radial-gradient(40rem 24rem at 100% 0, var(--cg-ink-glow), transparent 70%),
        var(--cg-ink-bg);
    border: 1px solid var(--cg-ink-border);
    border-radius: var(--cg-pub-radius-xl);
    overflow: hidden;
}

.cg-pub-promo-copy {
    align-self: center;
    padding: clamp(2rem, 5vw, 4rem);
}

.cg-pub .cg-pub-promo .cg-pub-display {
    color: var(--cg-ink-text);
}

.cg-pub .cg-pub-promo .cg-pub-lead {
    color: var(--cg-ink-text-muted);
}

.cg-pub-promo-mount {
    padding-block-start: clamp(2rem, 5vw, 4rem);
    padding-inline-start: clamp(2rem, 5vw, 4rem);
}

@media (min-width: 768px) {
    .cg-pub-promo-mount {
        padding-inline-start: 0;
    }
}

.cg-pub-promo .cg-mock {
    background: var(--cg-bg);
    border-inline-end: 0;
    border-bottom: 0;
    border-radius: 0;
    border-start-start-radius: var(--cg-pub-radius-lg);
    box-shadow: var(--cg-shadow-lg);
}

/* --------------------------------------------------------------------------
   Promo, centred — the closing statement without a preview beside it
   -------------------------------------------------------------------------- */

.cg-pub-promo.cg-pub-promo-center {
    background:
        radial-gradient(40rem 24rem at 50% 0, var(--cg-ink-glow), transparent 70%),
        var(--cg-ink-bg);
    text-align: center;
}

.cg-pub-promo-center > .cg-pub-promo-copy {
    max-width: 50rem;
    margin-inline: auto;
}

.cg-pub .cg-pub-promo-center .cg-pub-lead {
    margin-inline: auto;
}

.cg-pub-promo-center .cg-pub-actions {
    justify-content: center;
}

/* Tests find a closing panel's second action by its legacy cg-btn-outline-white
   class, which paints with literal colours and !important. Beside
   .cg-button-on-ink it is re-pointed at the ink tokens, so the class can stay. */
.cg-pub .cg-button-on-ink.cg-btn-outline-white {
    border: 1px solid var(--cg-ink-border) !important;
    color: var(--cg-ink-text) !important;
}

.cg-pub .cg-button-on-ink.cg-btn-outline-white:hover,
.cg-pub .cg-button-on-ink.cg-btn-outline-white:focus-visible {
    background-color: var(--cg-ink-border) !important;
    color: var(--cg-ink-text) !important;
}

/* --------------------------------------------------------------------------
   Motion — one reveal per section, driven by the scroll position itself.

   A scroll-driven animation needs no script and no observer, and because its
   progress is a function of where the page is, it cannot replay when Blazor
   swaps the prerendered markup for the interactive render. Browsers without
   animation-timeline simply show the content.
   -------------------------------------------------------------------------- */

@keyframes cg-pub-reveal {
    from {
        opacity: 0;
        transform: translateY(1.75rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
        .cg-reveal {
            animation: cg-pub-reveal linear both;
            animation-timeline: view();
            animation-range: entry 0% entry 45%;
        }
    }
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .cg-pub *,
    .cg-pub *::before,
    .cg-pub *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}

/* --------------------------------------------------------------------------
   Cookie consent — banner and preferences modal.

   Restyle only: CookieConsent.razor markup, consent logic and toggle state are
   unchanged, and every rule below keys on a class the component already emits.
   These selectors sit outside .cg-pub because the banner renders from
   PublicLayout, so they resolve global --cg-* tokens only — never the
   page-local .cg-pub aliases. They live in this shared stylesheet, not in a
   page one, because PublicLayout renders CookieConsent on every public page
   while a page stylesheet is loaded only on its own route.
   -------------------------------------------------------------------------- */

.cg-cookie-banner {
    padding: 1.25rem 1.5rem;
    background: var(--cg-bg-elevated);
    border-top: 1px solid var(--cg-border);
    box-shadow: var(--cg-shadow-lg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.cg-cookie-banner__inner {
    gap: 1.5rem 2rem;
}

.cg-cookie-banner__text {
    max-width: 68ch;
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--cg-text-secondary);
}

.cg-cookie-banner__text strong {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--cg-text-primary);
}

.cg-cookie-banner__learn-more {
    color: var(--cg-brand);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
}

/* Small accent text needs the lighter blue on a dark panel; --cg-brand fails AA
   at this size. */
[data-bs-theme="dark"] .cg-cookie-banner__learn-more {
    color: var(--cg-blue-400);
}

/* The theme sizes accept and decline but not customize, so the three buttons
   render at different heights. Size all three together. */
.cg-cookie-banner__btn-accept,
.cg-cookie-banner__btn-decline,
.cg-cookie-banner__btn-customize {
    font-size: 0.85rem !important;
    padding: 0.45rem 1.15rem !important;
    border-radius: 0.625rem;
    white-space: nowrap;
}

/* Preferences modal — same panel, border and radius system as the page. */

.cg-cookie-modal {
    border-radius: 0.875rem;
    background: var(--cg-bg-elevated);
    border: 1px solid var(--cg-border);
    box-shadow: var(--cg-shadow-lg);
}

.cg-cookie-modal__header {
    padding: 1.25rem 1.5rem 1rem;
    border-bottom: 1px solid var(--cg-border);
}

.cg-cookie-modal__title {
    color: var(--cg-text-primary);
}

.cg-cookie-modal__close {
    color: var(--cg-text-secondary);
    border-radius: 0.375rem;
}

.cg-cookie-modal__close:hover,
.cg-cookie-modal__close:focus-visible {
    color: var(--cg-text-primary);
}

.cg-cookie-modal__body {
    padding: 1.25rem 1.5rem;
    color: var(--cg-text-secondary);
}

.cg-cookie-modal__footer {
    padding: 1rem 1.5rem 1.25rem;
    border-top: 1px solid var(--cg-border);
    background: var(--cg-bg-subtle);
}

.cg-cookie-modal__footer .button {
    font-size: 0.85rem !important;
    padding: 0.45rem 1.15rem !important;
    border-radius: 0.625rem;
}

.cg-cookie-category {
    border-top: 1px solid var(--cg-border);
    padding: 1rem 0;
}

.cg-cookie-category strong {
    color: var(--cg-text-primary);
}

.cg-cookie-category__description {
    color: var(--cg-text-secondary);
    opacity: 1;
}

.cg-cookie-category__status {
    color: var(--cg-success);
}

.cg-cookie-toggle__slider {
    background: var(--cg-border-strong);
}

.cg-cookie-toggle__slider::after {
    background: var(--cg-slate-100);
}

.cg-cookie-toggle input:checked + .cg-cookie-toggle__slider {
    background: var(--cg-brand);
}

.cg-cookie-toggle input:focus-visible + .cg-cookie-toggle__slider {
    outline: 2px solid var(--cg-brand);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .cg-cookie-banner,
    .cg-cookie-banner *,
    .cg-cookie-modal,
    .cg-cookie-modal *,
    .cg-cookie-modal-backdrop {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
