/* =============================================================================
   cst-public.css — the public / Tier A component system

   Phase 3 Step 2 (docs/decisions.md D18): every comp class now carries the
   `cst-` prefix and the `.cst-page` scope is gone. Components are therefore
   collision-free and usable anywhere, not only inside a comp page wrapper.

   The nine classes that collided with real Tabler components — btn, card,
   grid, steps, tag, avatar, carousel, lead, stars — were the reason the scope
   existed. See docs/style-guide/06-migration.md for the full rename map.

   THE ELEMENT RESETS ARE NOW CLASSES
     .cst-h1 .cst-h2 .cst-h3 .cst-h4   were bare h1-h4
     .cst-p                             was bare p
     .cst-link-plain                    was bare a
     .cst-btn-reset                     was bare button
     .cst-media                         was bare img, svg
     .cst-typography                    was the .cst-page rule itself — the
                                        comp type context (17px Roboto/1.6).
                                        Nothing selects through it.
   `* { box-sizing }` was deleted — Tabler already sets it. `:focus-visible`
   and the reduced-motion block are now global; both are correct site-wide and
   neither can override an explicit style already in the tree.

   Generated by docs/tools/rename-comp-classes.py. Regenerating overwrites this
   file, so edit the script rather than the output while the alias block lives.
   ============================================================================= */

.cst-typography { -webkit-text-size-adjust:100%; background:var(--cst-surface); color:var(--cst-ink); font-family:Roboto,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; font-size:17px; line-height:1.6; -webkit-font-smoothing:antialiased }
.cst-media { display:block }

/* --- Mobile gutter ----------------------------------------------------------
   Tabler drops --tblr-page-padding from 1rem to 0.5rem below 992px, and every
   section on these pages takes its side padding from it through .container-xl
   (padding-inline: calc(--tblr-gutter-x * .5), where the gutter is that token
   doubled). 8px either side reads as no margin at all on a phone: headings and
   card edges sit against the bezel.

   Raising the token on the wrapper rather than restyling .container-xl keeps
   this inside Tabler's own mechanism - anything that reads the token inside
   <main> follows - and scopes it to the four pages that carry .cst-typography
   (home, /IACET/, /team-enrollment/, /onboarding/). The admin and account
   layouts are outside this wrapper and keep Tabler's value.

   1rem, i.e. Tabler's own desktop value, not a larger invented one: the column
   is already narrow at this width and the content should not be squeezed
   further than it needs to be. */
@media (max-width: 991.98px) {
	.cst-typography { --tblr-page-padding: 1rem; }
}

/* The guard against any full-bleed breakout turning into a horizontal scroll.
   c-theme.css carries the identical rule for its pages, with the same
   reasoning: overflow-x:clip behaves like hidden but does NOT establish a
   scroll container, so sticky positioning elsewhere still works. This file had
   no equivalent, which is why the navbar's over-wide brand lockup (see
   .cst-brand-logo in cst-components.css, fixed at source) was free to drag the
   whole page sideways on a phone. Belt and braces - the overflow itself is
   fixed, this stops the next one being a user-visible bug. */
body { overflow-x: clip; }

/* --- .cst-typography bare-element resets (D18 / Phase 4 Tier A) -------------
   The D18 rename turned the .cst-page bare-element rules into standalone
   classes (.cst-h1, .cst-p, .cst-media, .cst-link-plain, .cst-btn-reset). The
   Tier A pages use semantic elements, not those classes, so re-scope the same
   resets under .cst-typography — the wrapper that replaces .cst-page. Values
   are identical to the ALIAS block's .cst-page rules, so the swap is visually
   a no-op; this lets that block be deleted once all three Tier A pages carry
   .cst-typography instead of .cst-page. */
.cst-typography img, .cst-typography svg { display:block }
.cst-typography a { color:inherit; text-decoration:none }
.cst-typography button { font:inherit; color:inherit; border:0; background:none; cursor:pointer }
.cst-typography h1, .cst-typography h2, .cst-typography h3, .cst-typography h4 { margin:0; letter-spacing:0; line-height:1.28; font-weight:700; text-wrap:balance }
.cst-typography h1 { font-size:34px; font-weight:900; line-height:1.22 }
.cst-typography h2 { font-size:27px; font-weight:900 }
.cst-typography h3 { font-size:18px; font-weight:700; letter-spacing:0 }
.cst-typography p { margin:0 }
@media(min-width:64rem){
	.cst-typography h1 { font-size:44px }
	.cst-typography h2 { font-size:31px }
}
.cst-link-plain { color:inherit;text-decoration:none }
.cst-btn-reset { font:inherit;color:inherit;border:0;background:none;cursor:pointer }
:focus-visible { outline:2px solid var(--cst-accent); outline-offset:2px; border-radius:2px }
/* padding-block, NOT the `56px 0` shorthand it used to be. Most sections put
   .cst-sec on the band and .container-xl on a div inside it, where the two never
   met - but the home page also writes <section class="cst-sec container-xl">
   ("What operators get"), and there the shorthand's horizontal 0 overwrote the
   container's own gutter, because this file loads after tabler.min.css. That
   section ran flush to both screen edges. Vertical-only padding leaves the
   band-plus-inner-div case byte-identical (horizontal padding stays 0 there,
   which is what `0` was setting anyway) and lets the container keep its gutter
   when the two classes share an element. Same fix on .cst-hero below. */
.cst-sec { padding-block:56px }
.cst-band { background:var(--cst-band); border-top:1px solid var(--cst-border-subtle); border-bottom:1px solid var(--cst-border-subtle) }
.cst-band--tint { background:var(--cst-accent-pale); border-color:var(--cst-tint-band-border) }
.cst-band--sand { background:var(--cst-sand); border-color:var(--cst-sand-line) }
.cst-dark { background:var(--cst-ink); color:var(--cst-surface); border:0 }
.cst-dark--green { background:var(--cst-accent) }
.cst-dark--green .cst-card { background:var(--cst-dark-green-card);border-color:var(--cst-dark-green-border) }
.cst-dark--green .cst-bar { background:var(--cst-dark-green-border) }
.cst-dark--green .cst-eyebrow { color:var(--cst-badge) }
.cst-dark--green .cst-ico { color:var(--cst-badge) }
.cst-dark--green .cst-stat span { color:var(--cst-dark-green-stat) }
.cst-dark--green p { color:var(--cst-dark-green-text) }
.cst-dark--green .cst-statrow { border-top-color:var(--cst-dark-green-border) }
.cst-dark--green .cst-priceline { border-color:var(--cst-badge) }
.cst-band--accent { background:var(--cst-accent); color:var(--cst-surface); border:0 }
.cst-dark h2, .cst-band--accent h2, .cst-dark h3, .cst-band--accent h3, .cst-dark h4 { color:var(--cst-surface) }
.cst-dark p, .cst-band--accent p { color:var(--cst-dark-body-text) }
.cst-dark .cst-sub, .cst-band--accent .cst-sub { color:var(--cst-dark-sub-text) }
.cst-band--accent .cst-eyebrow { color:var(--cst-badge) }
.cst-dark .cst-card { background:var(--cst-dark-surface); border-color:var(--cst-ink-soft) }
.cst-dark .cst-card--hov:hover { box-shadow:0 4px 14px rgb(0 0 0 / 45%) }
.cst-dark .cst-card h3 { color:var(--cst-surface) }
.cst-dark .cst-card p { color:var(--cst-dark-card-text) }
.cst-dark .cst-kicker, .cst-dark .cst-role, .cst-dark .cst-meta, .cst-dark .cst-by, .cst-dark .cst-railcap, .cst-dark .cst-mcard p { color:var(--cst-dark-muted-text) }
.cst-dark .cst-ico { color:var(--cst-dark-icon) }
.cst-dark .cst-bar { background:var(--cst-ink-soft) }
.cst-dark .cst-tag { color:var(--cst-badge);background:transparent;border-color:var(--cst-gold) }
.cst-dark .cst-divider-line { background:var(--cst-ink-soft) }
.cst-band--tint .cst-card { background:var(--cst-surface);border-color:var(--cst-tint-band-border) }
.cst-band--sand .cst-card { background:var(--cst-surface);border-color:var(--cst-sand-line) }
.cst-band--sand .cst-step { border-top-color:var(--cst-sand-line) }
.cst-h1, .cst-h2, .cst-h3, .cst-h4 { margin:0; letter-spacing:0; line-height:1.28; font-weight:700; text-wrap:balance }
.cst-h1 { font-size:34px;font-weight:900;line-height:1.22 }
.cst-h2 { font-size:27px;font-weight:900 }
.cst-h3 { font-size:18px; font-weight:700; letter-spacing:0 }
.cst-p { margin:0 }
.cst-lead { font-size:18px; color:var(--cst-ink-soft); line-height:1.55; text-wrap:balance }
.cst-sub { font-size:17px;line-height:1.6; font-weight:500; color:var(--cst-ink-soft); margin-top:12px; max-width:none; text-wrap:balance }
.cst-eyebrow { font-size:13px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--cst-accent); margin-bottom:10px }
.cst-dark .cst-eyebrow { color:var(--cst-eyebrow-green) }
.cst-accent-text { color:var(--cst-accent) }
.cst-tnum { font-variant-numeric:tabular-nums }
.cst-head { margin-bottom:28px }
.cst-ico { width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;flex:none }
.cst-ico--sm { width:16px;height:16px;stroke-width:1.8 }
.cst-ico--20 { width:20px;height:20px }
.cst-ico--star { width:14px;height:14px;fill:var(--cst-terracotta);stroke:none }
/* border:0 belongs on the component, not on a page wrapper. Until the catalog
   cards, every .cst-btn in the codebase was an <a>, which has no UA border, so
   the missing declaration never showed. On a <button> it does — and the reset
   that used to cover it (.cst-typography button) is deliberately scoped, since
   making it global would strip .btn / .btn-close / .navbar-toggler site-wide.
   The variants that want a border declare their own below. */
.cst-btn { display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:13px 20px;border:0;border-radius:var(--cst-radius);font-weight:700;font-size:16px;transition:background .15s,color .15s,border-color .15s }
.cst-btn--p { background:var(--cst-accent);color:var(--cst-surface) }
.cst-btn--p:hover { background:var(--cst-accent-hover) }
.cst-btn--s { background:var(--cst-surface);color:var(--cst-accent);border:1px solid var(--cst-accent) }
.cst-btn--s:hover { background:var(--cst-accent-pale) }
.cst-btn--g { padding:10px 12px;font-weight:700 }
.cst-btn--g:hover { color:var(--cst-accent) }
.cst-btn--onDark { background:transparent;color:var(--cst-surface);border:1px solid var(--cst-surface) }
.cst-btn--onDark:hover { background:rgb(255 255 255 / 12%) }
.cst-btn--sm { padding:10px 16px;font-size:15px }
/* The wrapper element resets — .cst-typography a / .cst-oc-page a { color:inherit }
   and .cst-typography button { color:inherit;background:none } — are (0,1,1),
   which outranks the single-class .cst-btn--* rules above. Inside those wrappers
   a primary button kept its green fill but drew its label in the inherited body
   colour instead of white (and a <button> lost the fill outright). Re-assert fill
   and label with an element qualifier: (0,1,1) beats the resets, and still loses
   to the two-class band overrides below (.cst-band--accent / .cst-oc-final-cta),
   so the inverted-on-accent buttons are unaffected. Hover needs no twin — the
   :hover rules above are already (0,2,0). */
a.cst-btn--p, button.cst-btn--p { background:var(--cst-accent);color:var(--cst-surface) }
a.cst-btn--s, button.cst-btn--s { background:var(--cst-surface);color:var(--cst-accent) }
a.cst-btn--onDark, button.cst-btn--onDark { background:transparent;color:var(--cst-surface) }
/* Link inside a sentence. The same wrapper resets strip colour and underline
   from every anchor — right for cards and buttons, but it leaves a prose link
   indistinguishable from the text around it. Element-qualified for the same
   specificity reason as the buttons above. */
a.cst-inline-link { color:var(--cst-accent);text-decoration:underline;text-underline-offset:2px }
a.cst-inline-link:hover { color:var(--cst-accent-hover) }
.cst-card { background:var(--cst-surface);border:1px solid var(--cst-border);border-radius:var(--cst-radius) }
.cst-card--hov { transition:box-shadow .15s }
.cst-card--hov:hover { box-shadow:var(--cst-shadow-hover) }
.cst-pill { display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:500;padding:4px 9px;border-radius:2px;letter-spacing:.01em }
.cst-pill--badge { background:var(--cst-badge);color:var(--cst-badge-pill-text) }
.cst-pill--accent { background:var(--cst-accent-pale);color:var(--cst-accent) }
.cst-pill--warn { background:var(--cst-terracotta-pale);color:var(--cst-warm-text) }
.cst-tag { display:inline-block;font-size:12px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--cst-ink);background:var(--cst-terracotta-pale);border:1px dashed var(--cst-terracotta);padding:2px 6px;border-radius:2px;vertical-align:middle }
.cst-ph { position:relative;overflow:hidden;border-radius:var(--cst-radius); background: radial-gradient(120% 90% at 0% 0%, rgb(255 255 255 / 55%) 0%, rgb(255 255 255 / 0%) 45%), radial-gradient(120% 110% at 100% 100%, rgb(28 29 31 / 55%) 0%, rgb(28 29 31 / 0%) 55%), linear-gradient(135deg, var(--cst-accent-pale) 0%, var(--cst-accent) 100%); }
.cst-ph::after { content:"";position:absolute;inset:0;opacity:.12;mix-blend-mode:overlay;pointer-events:none; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.cst-ph__mark { position:absolute;inset:0;display:flex;align-items:center;justify-content:center }
.cst-ph__mark svg { width:64px;height:64px;stroke:var(--cst-surface);opacity:.3;stroke-width:1.2;fill:none }
.cst-ph--sm .cst-ph__mark svg { width:40px;height:40px }
.cst-ph__cap { position:absolute;left:12px;bottom:12px;right:56px;background:rgb(28 29 31 / 78%);color:var(--cst-surface);font-size:12px;line-height:1.35;padding:7px 10px;border-radius:2px }
.cst-ph__flag { position:absolute;top:10px;right:10px;background:var(--cst-ink);color:var(--cst-terracotta);font-size:12px;font-weight:700;letter-spacing:.04em;padding:4px 8px;border-radius:2px;z-index:2 }
.cst-r-16-9 { aspect-ratio:16/9 }
.cst-r-16-10 { aspect-ratio:16/10 }
.cst-r-4-3 { aspect-ratio:4/3 }
.cst-mockbar { background:var(--cst-terracotta);color:var(--cst-ink);font-size:12px;font-weight:600;text-align:center;padding:9px 16px;letter-spacing:.01em }
.cst-hero-band { background:linear-gradient(180deg,var(--cst-hero-band-bottom) 0%,var(--cst-hero-band-top) 100%);border-bottom:1px solid var(--cst-hero-band-border) }
/* Vertical only - see the note on .cst-sec. The hero is the one element on the
   home page written as <div class="cst-hero container-xl">, so the old
   `44px 0 52px` zeroed its gutter and the h1, the lead and the CTA buttons all
   started at x=0 on a phone. */
.cst-hero { padding-block:44px 52px }
.cst-hero__grid { display:grid;gap:34px }
.cst-hero h1 { margin-bottom:16px }
.cst-hero .cst-lead { max-width:56ch }
.cst-hero__cta { display:flex;flex-wrap:wrap;gap:12px;margin-top:24px }
.cst-trustline { display:flex;flex-wrap:wrap;align-items:center;gap:10px 18px;margin-top:24px;font-size:15px;font-weight:500;color:var(--cst-muted) }
.cst-trustline span { display:inline-flex;align-items:center;gap:7px }
.cst-trustline i { width:1px;height:14px;background:var(--cst-border);display:none }
@media(min-width:48rem) {
	.cst-trustline i { display:block }
}
.cst-hero__media { position:relative }
.cst-dashcard { display:none;position:absolute;left:16px;bottom:16px;width:262px;background:var(--cst-surface);border:1px solid var(--cst-border);border-radius:var(--cst-radius);padding:14px }
.cst-dashcard h4 { font-size:14px;font-weight:700;letter-spacing:0;margin-bottom:10px }
.cst-drow { display:flex;align-items:center;gap:8px;margin-bottom:9px;font-size:13px;color:var(--cst-muted) }
.cst-drow b { color:var(--cst-ink);font-size:13px;margin-left:auto;font-variant-numeric:tabular-nums }
.cst-drow .cst-lbl { width:64px;flex:none }
.cst-bar { flex:1;height:4px;background:var(--cst-border-subtle);border-radius:2px;overflow:hidden }
.cst-bar i { display:block;height:100%;background:var(--cst-accent);border-radius:2px }
.cst-bar i.cst-warn { background:var(--cst-terracotta) }
.cst-dashcard .cst-note { font-size:12px;color:var(--cst-muted);margin-top:4px }
@media(min-width:48rem) {
	.cst-dashcard { display:block }
}
@media(min-width:64rem) {
	.cst-hero__grid { grid-template-columns:1.05fr .95fr;align-items:center;gap:56px }
	.cst-h1 { font-size:44px }
	.cst-h2 { font-size:31px }
}
.cst-trustbar { padding:28px 0 }
.cst-trustbar p { text-align:center;font-size:16px;font-weight:500;color:var(--cst-muted) }
.cst-logos { display:flex;flex-wrap:wrap;justify-content:center;gap:14px 26px;margin-top:18px }
.cst-logoph { width:124px;height:44px;background:var(--cst-logo-placeholder);border-radius:2px;display:flex;align-items:center;justify-content:center;gap:6px;color:var(--cst-surface);font-size:12px;font-weight:500;letter-spacing:.06em }
.cst-logoph svg { width:16px;height:16px;stroke:var(--cst-surface);stroke-width:1.6;fill:none }
.cst-tabs { display:flex;gap:22px;overflow-x:auto;border-bottom:1px solid var(--cst-border);margin:26px 0 22px;scrollbar-width:none;-webkit-overflow-scrolling:touch }
.cst-tabs::-webkit-scrollbar { display:none }
.cst-tab { font-size:16px;font-weight:500;color:var(--cst-muted);padding:0 0 12px;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-1px }
.cst-tab:hover { color:var(--cst-ink) }
.cst-tab[aria-selected="true"] { color:var(--cst-ink);font-weight:700;border-bottom-color:var(--cst-ink) }
.cst-carousel { position:relative }
.cst-track { display:grid;grid-auto-flow:column;grid-auto-columns:264px;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:6px;scrollbar-width:none }
.cst-track::-webkit-scrollbar { display:none }
.cst-track>* { scroll-snap-align:start }
/* The doubled class is deliberate, not a typo. .cst-arrow is a <button> and the
   only page that uses it sits inside .cst-typography, whose
   `button { background:none; border:0 }` reset is a class-plus-element rule -
   specificity (0,1,1), which outranks a bare .cst-arrow at (0,1,0). The arrows
   therefore painted as naked chevrons floating over the cards. Repeating the
   class lifts this to (0,2,0) without naming the wrapper, so the rule holds
   wherever the component is used. Same root cause as the .cst-btn note above. */
.cst-arrow.cst-arrow { display:none;position:absolute;top:calc(50% - 22px);z-index:5;width:44px;height:44px;border-radius:999px;background:var(--cst-surface);border:1px solid var(--cst-border);align-items:center;justify-content:center;box-shadow:var(--cst-shadow-hover) }
.cst-arrow.cst-arrow:hover { background:var(--cst-band) }
/* The track is a single-line scroller, so an arrow sitting at a scroll limit has
   nothing to do. Say so, rather than leaving a live-looking control that ignores
   clicks - which is exactly how the arrows read before they had a handler. */
.cst-arrow.cst-arrow[disabled] { opacity:.35;cursor:default;box-shadow:none }
.cst-arrow.cst-arrow[disabled]:hover { background:var(--cst-surface) }
.cst-arrow--l { left:-14px }
.cst-arrow--r { right:-14px }
@media(min-width:48rem) {
	/* Doubled to match the base rule above - a single class would now lose to it
	   and the arrows would stay hidden at every width. */
	.cst-arrow.cst-arrow { display:flex }
}
.cst-ccard { display:flex;flex-direction:column }
.cst-ccard__body { padding:12px 12px 14px }
.cst-ccard h3 { font-size:16px;line-height:1.35;margin-bottom:5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden }
.cst-ccard .cst-by { font-size:14px;color:var(--cst-muted) }
.cst-rating { display:flex;align-items:center;gap:6px;margin-top:8px;font-size:13px }
.cst-rating b { color:var(--cst-gold);font-size:15px;font-variant-numeric:tabular-nums }
.cst-rating .cst-stars { display:flex;gap:1px }
.cst-rating .cst-cnt { color:var(--cst-muted);font-weight:500;font-size:13px }
.cst-meta { font-size:14px;color:var(--cst-muted);margin-top:8px }
.cst-badges { display:flex;flex-wrap:wrap;gap:6px;margin-top:9px }
.cst-price { margin-top:12px;font-size:17px;font-weight:700 }
.cst-price s { font-weight:400;font-size:14px;color:var(--cst-muted);margin-left:7px }
.cst-rail { margin-top:8px;background:var(--cst-surface);border:1px solid var(--cst-border);border-radius:var(--cst-radius);padding:26px 24px }
.cst-railrow { margin-bottom:28px }
.cst-railrow:last-of-type { margin-bottom:22px }
/* Label text is ink, not --cst-rail-label: the burnt-orange reads as a second
   warning colour next to the peach fill and terracotta border, which already
   carry the "without" signal. --cst-ink on --cst-terracotta-pale is 13.64:1
   (01-foundations.md contrast table). The token still drives the .cst-gap
   handoff markers below, where the warm colour is the point. This rule alone
   does not reach the homepage rail — see the .cst-dark .cst-rail block after
   .cst-railcap. */
.cst-raillabel { display:inline-flex;align-items:center;gap:8px;font-size:14px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--cst-ink);background:var(--cst-terracotta-pale);border:1px solid var(--cst-terracotta);border-radius:2px;padding:4px 10px;margin-bottom:14px }
.cst-raillabel.cst-on { color:var(--cst-surface);background:var(--cst-accent);border-color:var(--cst-accent) }
.cst-segs { display:flex;align-items:stretch;gap:0 }
.cst-seg { flex:1;border:2px solid;border-radius:var(--cst-radius);padding:14px 12px;display:flex;align-items:center;gap:9px;font-size:15px;font-weight:700;min-width:0 }
.cst-seg small { display:block;font-size:14px;font-weight:500;color:var(--cst-muted);margin-top:3px }
.cst-seg span { min-width:0 }
.cst-seg b { display:block;font-weight:700;line-height:1.25 }
.cst-seg--a { background:var(--cst-segment-a-bg);border-color:var(--cst-logo-blue);color:var(--cst-ink) }
.cst-seg--a small { color:var(--cst-segment-a-text) }
.cst-seg--b { background:var(--cst-terracotta-pale);border-color:var(--cst-terracotta);color:var(--cst-ink) }
.cst-seg--b small { color:var(--cst-warm-text) }
.cst-seg--c { background:var(--cst-segment-c-bg);border-color:var(--cst-segment-c-border);color:var(--cst-ink) }
.cst-seg--c small { color:var(--cst-segment-c-text) }
.cst-gap { width:78px;flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;font-weight:700;color:var(--cst-rail-label);text-align:center;line-height:1.15;position:relative }
.cst-gap::before { content:"";position:absolute;left:50%;top:8px;bottom:8px;width:0;border-left:2px dashed var(--cst-terracotta);transform:translateX(-50%);opacity:.55 }
.cst-gap svg { stroke:var(--cst-rail-label);position:relative;background:var(--cst-surface);border-radius:2px }
.cst-gap em { position:relative;background:var(--cst-surface);font-style:normal;padding:2px 3px }
.cst-cont { display:flex;border:2px solid var(--cst-accent);border-radius:var(--cst-radius);overflow:hidden;background:var(--cst-accent) }
.cst-cont .cst-seg { border:0;border-radius:0;background:transparent;color:var(--cst-surface) }
.cst-cont .cst-seg small { color:var(--cst-segment-contrast-text) }
.cst-cont .cst-seg+.cst-seg { border-left:2px solid rgb(255 255 255 / 35%) }
.cst-railcap { font-size:17px;line-height:1.6;font-weight:500;color:var(--cst-ink-soft);margin-top:16px;max-width:78ch;text-wrap:balance }
/* The rail is a WHITE card sitting inside the .cst-dark band, and the band's
   descendant rules assume everything under it is on dark: .cst-dark p (line 71)
   and .cst-dark .cst-railcap (line 78) are both two-class, so they outrank the
   one-class component rules above. The labels were painting #dbe2ec on peach
   and the captions #a9b6c9 on white — light-on-dark colours over a light
   surface. Re-assert the light-surface colours, scoped to the rail, at three
   classes. Anything in the rail that is not a <p> (the segments, the .cst-gap
   markers) never inherited the band colours and is left alone. */
.cst-dark .cst-rail .cst-raillabel { color:var(--cst-ink) }
.cst-dark .cst-rail .cst-raillabel.cst-on { color:var(--cst-surface) }
.cst-dark .cst-rail .cst-railcap { color:var(--cst-ink-soft) }
.cst-quotecard { background:var(--cst-surface);border:1px solid var(--cst-border);border-left:3px solid var(--cst-accent);border-radius:var(--cst-radius);padding:20px 22px;display:flex;gap:14px;margin-top:8px }
.cst-quotecard svg { stroke:var(--cst-accent);width:20px;height:20px;flex:none;margin-top:3px }
.cst-quotecard p { font-size:19px;line-height:1.55;font-weight:500;color:var(--cst-ink-soft);line-height:1.5 }
@media(max-width:47.99rem) {
	.cst-segs { flex-direction:column;gap:0 }
	.cst-gap { width:100%;flex-direction:row;padding:10px 0;gap:8px }
	.cst-gap::before { left:0;right:0;top:50%;bottom:auto;width:auto;height:0;border-left:0;border-top:2px dashed var(--cst-terracotta);transform:none }
	.cst-cont { flex-direction:column }
	.cst-cont .cst-seg+.cst-seg { border-left:0;border-top:1px solid rgb(22 38 60 / 22%) }
}
.cst-grid { display:grid;gap:20px }
@media(min-width:48rem) {
	.cst-g2 { grid-template-columns:repeat(2,1fr) }
	.cst-g3 { grid-template-columns:repeat(3,1fr) }
}
@media(min-width:64rem) {
	.cst-g4 { grid-template-columns:repeat(4,1fr) }
	.cst-g3 { grid-template-columns:repeat(3,1fr) }
}
@media(min-width:48rem) and (max-width:63.99rem) {
	.cst-g4 { grid-template-columns:repeat(2,1fr) }
}
.cst-bcard { padding:22px }
.cst-bcard .cst-ico { color:var(--cst-accent);margin-bottom:12px }
.cst-bcard .cst-kicker { font-size:13px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--cst-muted);margin-bottom:6px }
.cst-bcard p { font-size:16px;line-height:1.6;font-weight:400;color:var(--cst-ink-soft);margin-top:8px }
.cst-rcard { padding:22px }
.cst-rcard--lead { border-top:3px solid var(--cst-accent) }
.cst-rcard .cst-ico { color:var(--cst-accent);margin-bottom:12px }
.cst-rcard ul { list-style:none;margin:14px 0 0;padding:0 }
.cst-rcard li { display:flex;gap:10px;font-size:16px;color:var(--cst-ink-soft);margin-bottom:9px;line-height:1.45 }
.cst-rcard li svg { stroke:var(--cst-accent);flex:none;margin-top:3px }
.cst-rcard .cst-role { font-size:14px;color:var(--cst-muted);margin-top:4px }
.cst-qcard { padding:22px;display:flex;flex-direction:column }
.cst-qcard>svg { stroke:var(--cst-accent);width:22px;height:22px;margin-bottom:12px }
.cst-qcard p { font-size:17px;color:var(--cst-ink-soft);line-height:1.55 }
.cst-qcard .cst-who { display:flex;align-items:center;gap:11px;margin-top:auto;padding-top:18px }
.cst-avatar { width:48px;height:48px;border-radius:999px;flex:none;position:relative;overflow:hidden }
.cst-avatar .cst-ph__flag { display:none }
.cst-qcard .cst-name { font-size:15px;font-weight:700 }
.cst-qcard .cst-title { font-size:14px;color:var(--cst-muted) }
.cst-qcard--empty { border-style:dashed;opacity:.5;align-items:flex-start;justify-content:center;min-height:200px }
.cst-qcard--empty p { font-size:15px;font-weight:500;color:var(--cst-muted) }
.cst-tile { overflow:hidden;display:flex;flex-direction:column }
.cst-tile__body { padding:18px }
.cst-tile p { font-size:16px;line-height:1.6;font-weight:500;color:var(--cst-ink-soft);margin-top:7px }
.cst-tile a { display:inline-flex;align-items:center;gap:6px;color:var(--cst-logo-blue);font-weight:700;font-size:15px;margin-top:14px }
.cst-steps { display:grid;gap:26px;margin-top:8px }
.cst-step { padding-top:20px;border-top:1px solid var(--cst-border) }
.cst-step .cst-num { font-size:28px;font-weight:700;color:var(--cst-accent);letter-spacing:-.03em;line-height:1 }
.cst-step .cst-ico { color:var(--cst-accent);margin:12px 0 10px }
.cst-step p { font-size:16px;line-height:1.6;font-weight:500;color:var(--cst-ink-soft);margin-top:7px }
@media(min-width:48rem) {
	.cst-steps { grid-template-columns:repeat(3,1fr);gap:32px }
}
.cst-teams__grid { display:grid;gap:32px }
.cst-dark h2 { color:var(--cst-surface) }
.cst-dark p { color:var(--cst-dark-body-text) }
.cst-teams .cst-priceline { font-size:14px;color:var(--cst-surface);font-weight:600;margin-top:18px;padding:10px 14px;border:1px solid var(--cst-eyebrow-green);border-radius:var(--cst-radius);display:inline-block }
/* Link inside the price line. .cst-inline-link is accent green and would
   disappear against the green band, so this one takes the badge yellow the
   band already uses for the eyebrow and this pill's own border. */
.cst-teams .cst-priceline a { color:var(--cst-badge);text-decoration:underline;text-underline-offset:2px }
.cst-teams .cst-priceline a:hover { color:var(--cst-surface) }
.cst-teams__cta { display:flex;flex-wrap:wrap;gap:12px;margin-top:20px }
.cst-statrow { display:grid;gap:18px;margin-top:44px;padding-top:28px;border-top:1px solid var(--cst-ink-soft) }
.cst-stat b { display:block;font-size:30px;font-weight:700;letter-spacing:-.03em;color:var(--cst-surface);font-variant-numeric:tabular-nums }
.cst-stat span { font-size:15px;font-weight:500;color:var(--cst-dark-muted-text);display:block;margin-top:4px }
@media(min-width:48rem) {
	.cst-teams__grid { grid-template-columns:1.1fr .9fr;align-items:center;gap:48px }
	.cst-statrow { grid-template-columns:repeat(4,1fr) }
}
.cst-mcard { padding:20px }
.cst-mcard__top { display:flex;align-items:flex-start;justify-content:space-between;gap:10px }
.cst-mcard .cst-big { font-size:32px;font-weight:700;letter-spacing:-.03em;font-variant-numeric:tabular-nums }
.cst-mcard__top .cst-ico { color:var(--cst-muted);opacity:.45 }
.cst-mcard h3 { font-size:17px;margin-top:6px }
.cst-mcard p { font-size:15px;line-height:1.55;font-weight:500;color:var(--cst-ink-soft);margin-top:6px }
.cst-mcard .cst-bar { margin-top:14px;height:4px }
.cst-mcard .cst-plabel { font-size:13px;color:var(--cst-terracotta-ink);font-weight:700;margin-top:10px }
.cst-final { text-align:center }
.cst-final p { margin:16px auto 0;max-width:60ch;color:var(--cst-ink-soft);font-size:19px;font-weight:500;line-height:1.6;text-wrap:balance }
.cst-final .cst-btn { margin-top:24px }
.cst-final .cst-direct { font-size:16px;font-weight:500;color:var(--cst-muted);margin-top:18px }
.cst-band--accent .cst-final p { color:var(--cst-accent-band-text) }
.cst-band--accent .cst-final .cst-direct { color:var(--cst-accent-band-lead) }
.cst-band--accent .cst-btn--p { background:var(--cst-surface);color:var(--cst-accent-hover) }
.cst-band--accent .cst-btn--p:hover { background:var(--cst-accent-band-btn-hover) }
.cst-band--accent { position:relative }
.cst-band--accent::before { content:"";position:absolute;inset:0;pointer-events:none;opacity:.16; background-image:radial-gradient(rgb(255 255 255 / 85%) 1px, transparent 1px); background-size:18px 18px }
.cst-band--accent .container-xl { position:relative;z-index:1 }
.cst-ftr { padding:48px 0 0 }
.cst-ftr__grid { display:grid;gap:30px }
.cst-ftr h4 { font-size:15px;font-weight:700;letter-spacing:.02em;color:var(--cst-surface);margin-bottom:12px }
.cst-ftr ul { list-style:none;margin:0;padding:0 }
.cst-ftr li { margin-bottom:9px }
.cst-ftr a { font-size:16px;font-weight:500;color:var(--cst-footer-link) }
.cst-ftr a:hover { color:var(--cst-surface);text-decoration:underline }
.cst-ftr .cst-blurb { font-size:16px;line-height:1.6;font-weight:500;color:var(--cst-footer-text);max-width:34ch;margin-top:10px }
.cst-ftr__bot { margin-top:38px;padding:20px 0;border-top:1px solid var(--cst-ink-soft);display:flex;flex-wrap:wrap;gap:10px;justify-content:space-between;font-size:15px;font-weight:500;color:var(--cst-footer-text) }
.cst-ftr__bot a { font-size:15px;font-weight:700 }
@media(min-width:48rem) {
	.cst-ftr__grid { grid-template-columns:1.4fr 1fr 1fr 1fr }
}
@media(prefers-reduced-motion:reduce) {
	* { transition:none!important;animation:none!important;scroll-behavior:auto!important }
	.cst-track { scroll-snap-type:none }
}
.cst-oc-page h1, .cst-oc-page h2, .cst-oc-page h3 { margin: 0 0 .5em; font-weight: 700; line-height: 1.15; font-family: 'Roboto', system-ui, sans-serif; }
.cst-oc-page p { margin: 0 0 1em; color: var(--cst-ink-soft); }
.cst-oc-page img { max-width: 100%; display: block; }
.cst-oc-page a { color: inherit; }
/* …except a button. The a.cst-btn--* rules near line 127 already re-assert the
   button colours over a wrapper reset, but they only beat .cst-typography a
   because that one is declared ABOVE them. This reset is declared BELOW, at
   identical specificity (0,1,1), so on .cst-oc-page it won instead — every
   primary button on /team-enrollment/ and /onboarding/ kept its green fill and
   drew its label in the inherited body ink rather than white. Two classes plus
   the element settles it. The inverted buttons on the accent band are restated
   at the same weight further down (.cst-oc-final-cta), after these. */
.cst-oc-page a.cst-btn--p { color: var(--cst-surface); }
.cst-oc-page a.cst-btn--s { color: var(--cst-accent); }
.cst-oc-wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.cst-oc-eyebrow { display: inline-block; font-size: .78rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--cst-accent-hover); margin-bottom: .75em; }
.cst-oc-page .cst-oc-bleed { position: relative; isolation: isolate; }
.cst-oc-page .cst-oc-bleed::before { content: ''; position: absolute; inset-block: 0; left: calc(50% - 50vw); right: calc(50% - 50vw); z-index: -1; pointer-events: none; }
.cst-oc-stats-section::before { background: var(--cst-band); }
.cst-oc-section--alt::before { background: var(--cst-band); }
.cst-oc-final-cta::before { background: var(--cst-accent-hover); }
.cst-oc-hero { padding: 64px 0 48px; }
.cst-oc-hero .cst-oc-wrap { max-width: 760px; text-align: left; }
.cst-oc-hero h1 { font-size: clamp(2rem, 4.4vw, 3rem); color: var(--cst-ink); }
.cst-oc-hero h1 em { color: var(--cst-accent-hover); font-style: italic; }
.cst-oc-hero .cst-oc-lede { font-size: 1.15rem; max-width: 620px; }
.cst-oc-hero-bullets { list-style: none; margin: 28px 0 32px; padding: 0; display: grid; gap: 14px; }
.cst-oc-hero-bullets li { position: relative; padding-left: 30px; font-size: 1rem; color: var(--cst-ink); font-weight: 500; }
.cst-oc-hero-bullets li::before { content: ''; position: absolute; left: 0; top: .35em; width: 16px; height: 16px; border-radius: 5px; background: var(--cst-accent); }
.cst-oc-btn-row { display: flex; flex-wrap: wrap; gap: 14px; }

/* DEPRECATED 2026-09-17, and unused. Use .cst-btn / --p / --s (line ~108).

   This was a parallel button system on two landing pages: a 999px pill against
   the styleguide's var(--cst-radius), its own padding and font size, and a
   lift-and-shadow hover nothing else in the site does. It also hard-coded
   rgba(127,190,65,.35) rather than reading a token.

   Kept rather than deleted, per the don't-decommission rule - but do not reach
   for it. Anything that needs a button on those pages should use .cst-btn, and
   on the final CTA band the .cst-oc-final-cta overrides below invert it the way
   .cst-band--accent does on the home page. */
.cst-oc-btn { display: inline-block; padding: 14px 28px; border-radius: 999px; font-weight: 700; font-size: .95rem; text-decoration: none; transition: transform .15s ease, box-shadow .15s ease; cursor: pointer; border: none; }
.cst-oc-btn--primary { background: var(--cst-accent); color: var(--cst-surface); }
.cst-oc-btn--primary:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(127,190,65,.35); color: var(--cst-surface); text-decoration: none; }
.cst-oc-btn--secondary { background: transparent; color: var(--cst-ink); border: 2px solid var(--cst-ink); }
.cst-oc-btn--secondary:hover { background: var(--cst-ink); color: var(--cst-surface); text-decoration: none; }
.cst-oc-stats-section { padding: 36px 0; }
.cst-oc-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; text-align: center; }
.cst-oc-stat b { display: block; font-size: 2rem; color: var(--cst-ink); font-weight: 700; }
.cst-oc-stat span { font-size: .85rem; color: var(--cst-ink-soft); }
.cst-oc-section { padding: 72px 0; }
.cst-oc-section-head { max-width: 680px; margin-bottom: 40px; }
.cst-oc-section-head h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); color: var(--cst-ink); }
.cst-oc-course-groups { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.cst-oc-course-group { background: var(--cst-surface); border: 1px solid var(--cst-border-subtle); border-radius: var(--cst-radius); padding: 26px 28px; box-shadow: var(--cst-shadow-hover); }
.cst-oc-course-group h3 { font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--cst-accent-hover); font-weight: 700; margin-bottom: 14px; }
.cst-oc-course-group ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.cst-oc-course-group li b { display: block; color: var(--cst-ink); font-size: 1rem; font-weight: 700; }
.cst-oc-course-group li span { font-size: .92rem; color: var(--cst-ink-soft); }
.cst-oc-course-note { margin-top: 28px; max-width: 680px; font-size: .95rem; }
.cst-oc-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.cst-oc-step .cst-oc-num { font-size: .85rem; font-weight: 700; color: var(--cst-accent); letter-spacing: .05em; margin-bottom: 10px; display: block; }
.cst-oc-step h3 { font-size: 1.15rem; color: var(--cst-ink); }
.cst-oc-step p { font-size: .95rem; }
.cst-oc-price-card { background: var(--cst-ink); color: var(--cst-surface); border-radius: 20px; padding: 48px; display: grid; grid-template-columns: 1.1fr .9fr; gap: 40px; align-items: center; }
.cst-oc-price-card h2 { color: var(--cst-surface); }
.cst-oc-price-card p { color: var(--cst-border); }
.cst-oc-price-box { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.18); border-radius: var(--cst-radius); padding: 32px; text-align: center; }
/* White and bold, not muted grey: this sits inside .cst-oc-price-box on the dark
   .cst-oc-price-card, where --cst-muted is the colour of text meant to recede on
   a LIGHT surface and came out nearly illegible. The struck price is half the
   comparison the card is making, so it has to be readable. */
.cst-oc-price-old { font-size: 1.2rem; color: var(--cst-surface); font-weight: 700; text-decoration: line-through; }
.cst-oc-price-new { font-size: 3rem; font-weight: 700; color: var(--cst-surface); margin: 6px 0; }
.cst-oc-save-badge { display: inline-block; background: var(--cst-terracotta); color: var(--cst-ink); font-weight: 700; font-size: .82rem; border-radius: 999px; padding: 5px 14px; margin-bottom: 10px; }
.cst-oc-price-box .cst-oc-btn--primary { width: 100%; margin-top: 16px; display: block; text-align: center; }
.cst-oc-price-fine { font-size: .82rem; color: var(--cst-muted); margin-top: 14px; }
.cst-oc-price-footnote { margin-top: 28px; font-size: .92rem; color: var(--cst-ink-soft); }
.cst-oc-price-footnote a { color: var(--cst-accent-hover); font-weight: 700; text-decoration: underline; }
/* Team-enrollment row inside .cst-oc-price-card. Spans the card's two columns
   and re-splits on the same 1.1fr/.9fr ratio so its heading sits under the
   pricing copy and its text under the price box. The rule above it is the
   card's own hairline, repeated - the row is a second offer, not a footnote. */
.cst-oc-team-band { grid-column: 1 / -1; display: grid; grid-template-columns: 1.1fr .9fr; gap: 40px; align-items: center; margin-top: 8px; padding-top: 32px; border-top: 1px solid rgba(255,255,255,.18); }
/* Sized to match the card's h2 ("One price. Everything included.") so the two
   rows read as equal offers rather than an offer and a sub-note. The values are
   the .cst-typography h2 scale verbatim, including its 64rem step; it stays an
   h3 because it follows that h2 in the document. */
.cst-oc-team-band h3 { color: var(--cst-surface); font-size: 27px; margin: 0; }
@media (min-width: 64rem) {
	.cst-oc-team-band h3 { font-size: 31px; }
}
.cst-oc-team-band p { color: var(--cst-border); margin: 0 0 18px; }
/* The link sits on the dark card, where the footnote's --cst-accent-hover green
   is unreadable. Badge yellow is the treatment the other on-dark inline links
   already use. */
.cst-oc-team-band a:not(.cst-btn) { color: var(--cst-badge); font-weight: 700; text-decoration: underline; }
.cst-oc-faq { max-width: 760px; }
.cst-oc-faq details { border-bottom: 1px solid var(--cst-border-subtle); padding: 20px 0; }
.cst-oc-faq details summary { cursor: pointer; font-weight: 700; color: var(--cst-ink); list-style: none; display: flex; justify-content: space-between; align-items: center; font-size: 1.02rem; }
.cst-oc-faq details summary::-webkit-details-marker { display: none; }
.cst-oc-faq details summary::after { content: '+'; font-size: 1.4rem; color: var(--cst-accent); font-weight: 400; margin-left: 12px; flex-shrink: 0; }
.cst-oc-faq details[open] summary::after { content: '\2212'; }
.cst-oc-faq details p { margin-top: 14px; font-size: .95rem; }
.cst-oc-final-cta { color: var(--cst-surface); }
/* Centred as a block: the closing band is a single short column with one
   action, not a reading column, so a left edge with nothing beneath it reads
   as a stray. text-align carries the eyebrow, the heading and the footnote;
   the button row is flex and needs its own justification. */
.cst-oc-final-cta .cst-oc-wrap { max-width: 700px; text-align: center; }
.cst-oc-final-cta .cst-oc-btn-row { justify-content: center; }
/* The footnote under the button gets its own air. .cst-oc-page p sets only a
   bottom margin, so without this the enterprise-pricing line sat tight against
   the CTA and read as part of the button block. */
.cst-oc-final-cta .cst-oc-btn-row + p { margin-top: 24px; }
.cst-oc-final-cta h2 { color: var(--cst-surface); font-size: clamp(1.6rem, 3.2vw, 2.3rem); }
.cst-oc-final-cta p { color: var(--cst-accent-pale); font-size: 1.05rem; }

/* The band is dark green, so a normal primary button would be green on green.
   These are the same two rules .cst-band--accent applies on the home page, and
   they replace a pair of inline styles that hand-rolled the inversion with
   `background:##fff;color:var(--oc-green-dark)`. --oc-green-dark is defined
   NOWHERE - the colour declaration was dropped by the browser and the label
   fell back to the band's inherited near-white, giving white text on a white
   button. That is the "can't see the text" case; the token, not the markup, was
   the bug.

   Same for the eyebrow: it was `color:var(--oc-yellow)`, equally undefined,
   which is why it rendered in the default green against dark green. */
/* Element-qualified to match the .cst-oc-page a.cst-btn--p rule added above: at
   two classes it would have lost to that one and the inverted button would have
   gone white-on-white. Same weight, declared later, so the inversion still
   wins on this band and nowhere else. */
.cst-oc-final-cta a.cst-btn--p { background: var(--cst-surface); color: var(--cst-accent-hover); }
.cst-oc-final-cta a.cst-btn--p:hover { background: var(--cst-accent-band-btn-hover); color: var(--cst-accent-hover); }
.cst-oc-final-cta .cst-oc-eyebrow { color: var(--cst-badge); }
@media (max-width: 900px) {
	.cst-oc-course-groups { grid-template-columns: 1fr; }
	.cst-oc-steps { grid-template-columns: 1fr; gap: 36px; }
	.cst-oc-price-card { grid-template-columns: 1fr; padding: 32px; }
	/* Stacks with the card: heading over copy over button, same as the two
	   blocks above it collapse. */
	.cst-oc-team-band { grid-template-columns: 1fr; gap: 20px; }
}
@media (max-width: 600px) {
	.cst-oc-stats { grid-template-columns: 1fr; gap: 24px; }
	.cst-oc-hero { padding: 40px 0 32px; }
	.cst-oc-section { padding: 52px 0; }
}
/* The .cst-oc-page landing pages (/team-enrollment/, /onboarding/): same column
   width as the home page, and a hero that starts at the page's left edge rather
   than centred.

   WIDTH. The home page's sections use Bootstrap/Tabler's .container-xl, which
   is 1140px from the xl breakpoint and 1320px from xxl (1400px), with
   --tblr-page-padding of gutter either side. .cst-oc-wrap is a flat 1120px with
   24px gutters, so on a wide screen this page ran ~200px narrower than the home
   page and read as a different, tighter layout. The values below are
   .container-xl's, restated rather than inherited because .cst-oc-wrap is not a
   Bootstrap container - if Tabler's container scale ever changes, this is the
   one place to follow it.

   LEFT EDGE. .cst-oc-hero .cst-oc-wrap narrows the wrap to 760px while
   .cst-oc-wrap still carries margin:0 auto, so the whole hero BLOCK was centred
   inside the column every other section uses. text-align:left made the text
   ragged-left within that floating block, which is why it read as almost right:
   the h1 simply did not line up with the section headings below it. The hero now
   takes the full column and the MEASURE is capped on the copy instead, so line
   length stays readable while the left edge agrees with the rest of the page.
   (.cst-oc-lede caps itself at 620px.)

   Both selectors are spelled out so the hero does not depend on source order
   against .cst-oc-hero .cst-oc-wrap above.

   Scoped to .cst-oc-page, which is exactly these two pages and nothing else.
   This started life on .te-page while only Team Enrollment was in scope; once
   Onboarding wanted the same thing, one shared rule beat two identical ones.
   The .te-page class is still on that page's <main> as a hook, it just no
   longer carries these declarations. */
.cst-oc-page .cst-oc-wrap,
.cst-oc-page .cst-oc-hero .cst-oc-wrap {
	max-width: 1140px;
	padding-inline: var(--tblr-page-padding, 1rem);
}
@media (min-width: 1400px) {
	.cst-oc-page .cst-oc-wrap,
	.cst-oc-page .cst-oc-hero .cst-oc-wrap { max-width: 1320px; }
}
.cst-oc-page .cst-oc-hero h1,
.cst-oc-page .cst-oc-hero .cst-oc-hero-bullets { max-width: 760px; }

.cst-te-included-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: 40px; align-items: start; }
.cst-te-included-list { list-style: none; margin: 0; padding: 0; }
.cst-te-included-list li { display: flex; gap: 12px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--cst-border-subtle); font-size: 1.02rem; color: var(--cst-ink); }
.cst-te-included-list li:last-child { border-bottom: none; }
.cst-te-included-list li::before { content: '\2713'; color: var(--cst-accent); font-weight: 700; flex: 0 0 auto; }
.cst-te-journey { background: var(--cst-surface); border: 1px solid var(--cst-border-subtle); border-radius: var(--cst-radius); padding: 24px; box-shadow: var(--cst-shadow-hover); }
.cst-te-journey-label { font-size: .85rem; color: var(--cst-ink-soft); margin-bottom: 16px; }
.cst-te-journey-track { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* Numbered 1-12, so the track reads as the twelve courses rather than as
   decoration. Grown from 18px to 26px because "12" has to fit inside the
   circle at a legible size; the border and fill are unchanged. */
.cst-te-journey-dot { width: 26px; height: 26px; border-radius: 50%; background: var(--cst-accent-pale); border: 2px solid var(--cst-accent); flex: 0 0 auto; display: flex; align-items: center; justify-content: center; font-size: .72rem; font-weight: 700; line-height: 1; color: var(--cst-accent-hover); }
.cst-te-journey-arrow { color: var(--cst-ink-soft); margin: 0 6px; }
.cst-te-journey-badge { flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%; background: var(--cst-ink); color: var(--cst-surface); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .68rem; text-align: center; line-height: 1.1; padding: 4px; }
.cst-te-journey p:last-child { margin-top: 16px; margin-bottom: 0; font-size: .9rem; }
.cst-te-callout { max-width: 780px; font-size: 1.02rem; color: var(--cst-ink); }
/* Air above the first callout only. It follows the included-list / journey-card
   grid, and .cst-oc-page p carries no top margin, so it was butting up against
   the bottom of that block; the second callout keeps its normal paragraph
   rhythm underneath. */
.cst-te-included-grid + .cst-te-callout { margin-top: 32px; }
.cst-te-course-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 32px; margin-top: 8px; }
.cst-te-course-item { display: flex; gap: 12px; align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--cst-border-subtle); }
.cst-te-course-item .cst-te-n { font-weight: 700; color: var(--cst-accent-hover); font-size: 1rem; flex: 0 0 auto; min-width: 1.4rem; }
.cst-te-course-item .cst-te-t { font-size: 1rem; color: var(--cst-ink); }
.cst-te-toolkit-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.cst-te-toolkit-card { background: var(--cst-surface); border: 1px solid var(--cst-border-subtle); border-radius: var(--cst-radius); padding: 26px 28px; box-shadow: var(--cst-shadow-hover); }
.cst-te-toolkit-card h3 { font-size: 1.1rem; color: var(--cst-ink); margin-bottom: .4em; }
.cst-te-toolkit-card p { margin: 0; font-size: .96rem; }
.cst-te-pull { margin: 32px 0 0; padding: 20px 28px; border-left: 4px solid var(--cst-accent); background: var(--cst-accent-pale); border-radius: 0 var(--cst-radius) var(--cst-radius) 0; font-size: 1.08rem; color: var(--cst-ink); }
.cst-te-price-figure { font-size: 2.6rem; font-weight: 700; color: var(--cst-surface); }
.cst-te-price-figure span { font-size: 1.05rem; font-weight: 400; color: var(--cst-border); }
.cst-te-calc label { display: block; font-weight: 700; font-size: .9rem; margin-bottom: 10px; color: var(--cst-surface); }
.cst-te-calc-row { display: flex; align-items: center; justify-content: center; gap: 14px; }
.cst-te-calc-row input[type=number] { width: 5.5rem; padding: 10px 12px; font-size: 1rem; border: 1px solid rgba(255,255,255,.28); border-radius: 6px; background: rgba(255,255,255,.08); color: var(--cst-surface); }
.cst-te-calc-total { font-size: 1.5rem; font-weight: 700; color: var(--cst-surface); }
.cst-te-calc-note { font-size: .85rem; color: var(--cst-muted); margin: 14px 0 0; }
.cst-te-calc-note--warn { color: var(--cst-terracotta); font-weight: 700; }
@media (max-width: 900px) {
	.cst-te-included-grid { grid-template-columns: 1fr; }
	.cst-te-toolkit-grid { grid-template-columns: 1fr; }
	.cst-te-course-grid { grid-template-columns: 1fr; }
}

/* --- Catalog card (/menu/) --------------------------------------------------
   The home page's course card (.cst-ccard, above) reused as the catalog's
   product tile, replacing the bordered table the catalog used to render. The
   body above the price is unchanged; these rules add only what a real product
   needs and the home page comp did not have — a product image in place of the
   .cst-ph placeholder, and a footer holding the add-to-cart control.

   The two-class selectors are deliberate. /menu/ is a .c-theme page, and
   .c-theme p / .c-theme h3 are single-class-plus-element rules that would
   otherwise win the cascade and recolour the card's metadata. Anything that
   .c-theme also sets is therefore restated here at .cst-ccard--catalog X. */
.cst-ccard--catalog { height:100%;overflow:hidden }
.cst-ccard--catalog a { color:inherit;text-decoration:none }
/* A FIXED height, not an aspect-ratio box. Two reasons, both of which made
   product images render at a different size on every card:
     1. An aspect-ratio box has no definite height of its own, so the img's
        height:100% had nothing to resolve against and fell back to auto —
        each picture then sized itself from its own intrinsic proportions.
     2. The box is a flex item in a column card. Default flex-shrink let it
        compress whenever a stretched card redistributed space, so cards in
        the same row disagreed about how tall the image was.
   flex:0 0 auto plus a literal height settles both: identical box on every
   card, with object-fit cropping whatever the source image's shape is. */
/* Inset by the same 12px the body and the footer use, so the image, the text and
   the CTA all sit on one vertical edge instead of the image alone running full
   bleed. Height is 180 = the 168px picture the cards already had, plus the 12px
   that now sits above it, so insetting did not shrink the image.

   box-sizing:border-box is Tabler's, set site-wide; the padding therefore comes
   out of the 180 rather than adding to it, which is what keeps the picture at
   168 and every card in a row exactly as tall as its neighbours.

   The band background and the radius moved from the box to the img: with the
   picture inset, those belong to the picture, and the card's own surface is what
   shows in the margin around it. border-bottom went away with the same change -
   it existed to separate a full-bleed image from the body, and a rule running
   wider than the thing it underlines just reads as a mistake. */
.cst-ccard__media { display:block;flex:0 0 auto;height:180px;padding:12px 12px 0 }
.cst-ccard__media img { width:100%;height:100%;object-fit:cover;object-position:center;display:block;border-radius:var(--cst-radius);background:var(--cst-band) }
.cst-ccard--catalog .cst-ccard__body { flex:1 1 auto;display:flex;flex-direction:column }
.cst-ccard--catalog .cst-ccard__body h3 { font-size:16px;line-height:1.35;font-weight:700;color:var(--cst-ink) }
.cst-ccard--catalog .cst-by,
.cst-ccard--catalog .cst-meta { color:var(--cst-muted);line-height:1.45 }
/* The price moved out of the body and into the footer row, so it no longer needs
   margin-top:auto to reach the bottom of the card - the body's flex:1 1 auto
   above does that for the whole row, which is what keeps prices and CTAs aligned
   across cards whose titles wrap to different heights. */
.cst-ccard--catalog .cst-price { margin:0;color:var(--cst-ink);line-height:1.3 }
/* "Price" above the amount. Both spans are block so they stack inside the <p>
   without a <br>, and the label takes the muted treatment the card's other
   secondary text (.cst-by, .cst-meta) already uses, so it reads as a caption for
   the number rather than competing with it. */
.cst-price__label { display:block;font-size:var(--cst-text-sm);font-weight:500;color:var(--cst-muted);line-height:1.2 }
.cst-price__amt { display:block }
/* Price left, CTA right, on one line - with a real safety valve, because the CTA
   label is not fixed. These cards are 264px wide (240px inside the padding) and
   the button says anything from "Add to Cart" to "Add to My Courses", which is
   roughly 70px wider. The pair does not always fit.

   The button does not grow to fill the row - flex-grow:1 stretched it across
   whatever the price left behind and made a two-word CTA read as a banner. It
   also does not sit at bare content width, which left "Add to Cart" looking like
   an afterthought next to the price. min-width is the floor between those two:
   short labels are padded out to a deliberate button shape, long ones size to
   their own text and simply run wider. justify-content pushes it to the right
   edge either way.

   The floor is a FLOOR, not a width. Content wider than 8.75rem still wins, so
   adding a longer CTA later widens the button instead of truncating it - which
   is the failure a fixed width would have introduced.

   The wrap is driven by the button's own min-content width, not by a guessed
   breakpoint. white-space:nowrap makes min-content the full label, so when label
   + price + gap exceed the row the button drops to its own line intact. Nothing
   is ever squeezed, wrapped mid-label, or clipped: a truncated call to action is
   worse than a second line. Note the floor feeds into that calculation - raising
   it much past 9rem starts wrapping cards that fit today. */
/* Column gap is the space between the amount and the button and is set wider
   than the row gap on purpose - they are two different jobs. Row gap only
   applies once the button has wrapped onto its own line, where 10px sits it
   closer under the price than 18px would. */
.cst-ccard__foot { display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 18px;padding:0 12px 14px }
.cst-ccard__foot .cst-price { flex:0 0 auto }
.cst-ccard__cta { flex:0 0 auto;width:auto;min-width:8.75rem;white-space:nowrap }
.cst-ccard__cta[disabled] { background:var(--cst-band);color:var(--cst-muted);border:1px solid var(--cst-border);cursor:default }
.cst-ccard__cta[disabled]:hover { background:var(--cst-band) }

/* --- Catalog view switch (/menu/) -------------------------------------------
   Two icon buttons above the catalog, and the compact view they turn on. The
   compact view is the SAME card markup relaid as a row — there is no second
   rendering — so a change to the card cannot leave one of the two views behind.
   The .cst-viewtoggle__btn is a <button>, which /menu/ does not scope under
   .cst-typography, so it carries its own reset. */
.cst-viewtoggle { display:flex;justify-content:flex-end;gap:6px;margin-bottom:16px }
.cst-viewtoggle__btn { display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;padding:0;font-size:18px;line-height:1;cursor:pointer;background:var(--cst-surface);color:var(--cst-muted);border:1px solid var(--cst-border);border-radius:var(--cst-radius);transition:background .15s,color .15s,border-color .15s }
.cst-viewtoggle__btn:hover { color:var(--cst-accent);border-color:var(--cst-accent) }
.cst-viewtoggle__btn[aria-pressed="true"] { background:var(--cst-accent);border-color:var(--cst-accent);color:var(--cst-surface) }

/* One row per product. The grid stays a grid — only its track count changes —
   so the gap and the cards' own box model keep working. Two-class selectors
   throughout, same reason as the block above: .c-theme's element rules and the
   card's own one-class rules both have to be cleared. */
.cst-catalog--compact .cst-grid { grid-template-columns:1fr;gap:10px }
/* gap here is the one between the badge column and the price/CTA block, and it
   is wider than the card view's 14px on purpose: at full width those are three
   separate readings — what it covers, what it costs, what to do — and a tight
   gap runs them together. */
.cst-catalog--compact .cst-ccard--catalog { height:auto;flex-direction:row;align-items:center;gap:28px;padding:10px 12px }
/* No thumbnail in the compact view. It is display:none rather than removed from
   the markup because the card is rendered once and restyled — the card view
   still needs it. */
.cst-catalog--compact .cst-ccard__media { display:none }
/* The body becomes the scanning grid: the title and everything that belongs
   under it — .cst-by, and the .cst-meta line carrying minutes, CEUs and
   Certificate — stay stacked in a fluid first column. Only the .cst-badges
   group moves out, into a second column of its own.

   That column is auto-width, and the text column takes all the slack, so the
   badge group is pushed up against the price/CTA block and the pills end on a
   common right edge down the page.

   Every text child is pinned to column 1 explicitly. Without that, only the
   title landed there: auto-placement fills row by row, so with .cst-badges
   holding (row 1, column 2) the cursor wrapped to row 2, put .cst-by at
   (2,1) and then dropped .cst-meta into the next free cell — (2,2), directly
   under the badges. Pinning the column keeps minutes / CEU / Certificate under
   the title where they belong, whether or not .cst-by is present. */
.cst-catalog--compact .cst-ccard--catalog .cst-ccard__body { padding:0;min-width:0;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:24px }
.cst-catalog--compact .cst-ccard__body > h3,
.cst-catalog--compact .cst-ccard__body > .cst-by,
.cst-catalog--compact .cst-ccard__body > .cst-meta { grid-column:1 }
/* Centred against the whole text stack, not pinned to the title's row.
   span 3 is the ceiling, not a guess: column 1 holds at most h3 + .cst-by +
   .cst-meta, and the last two are conditional. A product with fewer leaves an
   empty implicit row, which costs nothing — implicit rows are auto-sized and
   row-gap is 0, so an empty one is 0 tall. align-self then centres the pills
   across whatever the span actually resolved to. */
.cst-catalog--compact .cst-ccard__body > .cst-badges { grid-column:2;grid-row:1 / span 3;align-self:center;margin-top:0;flex-wrap:nowrap }
/* One row of pills, not a stack: .cst-badges wraps by default because the card
   view is 264px wide, and nothing here is. */
.cst-catalog--compact .cst-badges .cst-pill { white-space:nowrap }
/* One line per title here — the point of the view is scanning a list, and a
   card that wraps to two lines makes the rows disagree about their height. */
.cst-catalog--compact .cst-ccard h3 { -webkit-line-clamp:1;margin-bottom:2px }
/* Price and CTA stop being a footer row and become the right-hand end of the
   line. nowrap keeps them there: the wrap the card view needs at 264px wide is
   not needed at full width, and letting it happen would stagger the rows. */
.cst-catalog--compact .cst-ccard__foot { flex:0 0 auto;flex-wrap:nowrap;justify-content:flex-end;gap:28px;padding:0 }
.cst-catalog--compact .cst-ccard--catalog .cst-price { text-align:right }
@media(max-width:47.99rem) {
	/* Narrow screens: let the price/CTA pair drop under the text rather than
	   squeezing the title into a few characters. */
	.cst-catalog--compact .cst-ccard--catalog { flex-wrap:wrap }
	.cst-catalog--compact .cst-ccard__foot { flex:1 1 100% }
	/* There is no room for a pill column beside the text at this width, so the
	   badges go back under it, the grid collapses to one track, and they are
	   allowed to wrap again. */
	.cst-catalog--compact .cst-ccard--catalog .cst-ccard__body { grid-template-columns:minmax(0,1fr) }
	.cst-catalog--compact .cst-ccard__body > .cst-badges { grid-column:1;grid-row:auto;margin-top:9px;flex-wrap:wrap }
}
