/* ===========================================================================
   DesiCrew theme override
   ---------------------------------------------------------------------------
   Loaded AFTER the compiled base stylesheet (see src/layouts/Shell.astro), so
   these declarations win the cascade. We remap the *base colour scales* (which
   are defined only once, in :root) — every semantic token references them via
   var(), so overriding the scales recolours both light and dark themes safely.
   A handful of light-mode canvas tokens are hardcoded, so we override those in
   :root and re-assert their dark values under .dark/.lg:dark to avoid leaking
   the light value into dark sections.

   Brand: DesiCrew — brand book primary: Oxford Blue #011C46, Persian Blue
   #0B44CF, Tufts Blue #1892E5, Mint #22D2A2; secondary: French Rose #FD4C8C,
   Sunglow #FFD23F, Lavender #E7EDFB, Mint Green #DEF8F1, Alice Blue #E8F5FD.
   The logo SVG keeps its original (hardcoded) colours by design.
   =========================================================================== */

/* Typeface II — Space Grotesk (self-hosted). Proportional (NON-mono) evolution of
   the brand book's Space Mono: same technical character for labels/eyebrows/chips,
   without the monospacing. One variable file (weights 300–700) so 600/700 labels
   never faux-bold. Split latin / latin-ext to mirror Google's subsets. */
@font-face {
  font-family: "Space Grotesk";
  src: url(/fonts/space-grotesk/SpaceGrotesk-Variable-latin.woff2) format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  src: url(/fonts/space-grotesk/SpaceGrotesk-Variable-latin-ext.woff2) format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* --- Typeface I: Helvetica Neue (display/UI). Typeface II: Space Grotesk. ---
     Helvetica Neue is a system font, so no font file is needed. */
  --font-main: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-inter: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* --- Typeface II: labels/eyebrows/chips. Token keeps its historical name
     `--font-mono` (drives ~399 .font-mono usages) but now resolves to a
     PROPORTIONAL face — Space Grotesk, the non-mono sibling of Space Mono. --- */
  --font-mono: "Space Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* === Primary accent: orange ramp -> DesiCrew blue ramp (peaks Persian Blue).
     --color-orange-strong (=orange-500) drives surface-brand, text-brand-1 and
     all primary CTAs/highlights. */
  --color-orange-50:  #e9f0ff;
  --color-orange-100: #cfe0ff;
  --color-orange-200: #9bc2fb;
  --color-orange-400: #2e73e8;
  --color-orange-500: #0b44cf; /* Persian Blue — primary brand accent */
  --color-orange-600: #093bb0;

  /* orange-medium = tangerine-500 (= text-brand-5). -> Tufts Blue family */
  --color-tangerine-500: #1892e5; /* Tufts Blue */
  --color-tangerine-700: #0f6fb5;
  --color-tangerine-800: #0b5286;

  /* === Secondary accents === */
  /* Yellow -> Sunglow */
  --color-yellow-300: #ffe383;
  --color-yellow-400: #ffd23f; /* Sunglow */
  --color-yellow-500: #f5c000;

  /* Green -> Mint */
  --color-green-300: #8fe8ce;
  --color-green-500: #22d2a2; /* Mint */
  --color-green-700: #1aa886;
  --color-green-900: #0c6b57;

  /* Pink -> French Rose */
  --color-pink-200: #ffd0e2;
  --color-pink-300: #fe9dbe;
  --color-pink-600: #fd4c8c; /* French Rose */
  --color-pink-800: #b0245e;

  /* === Blue scale -> DesiCrew blues.
     --color-blue-strong (=blue-600) drives text-brand-2. */
  --color-blue-200: #c3e2fb;
  --color-blue-400: #6fc0f5;
  --color-blue-600: #1892e5; /* Tufts Blue */
  --color-blue-800: #0a3fa8; /* Persian-ish (blue-contrast) */

  /* === Navy scale -> Oxford Blue ramp.
     navy-950 = black-strong = dark canvas + light-mode surface-invert. */
  --color-navy-200: #d5deec;
  --color-navy-300: #a9b8d2;
  --color-navy-500: #6e84a8; /* border-brand */
  --color-navy-600: #54688c;
  --color-navy-700: #243f66;
  --color-navy-800: #082a57; /* black-light  -> surface-brand-tertiary (dark) */
  --color-navy-900: #04204a; /* black-medium -> surface-brand-secondary (dark) */
  --color-navy-950: #011c46; /* black-strong -> Oxford Blue */

  /* === Cream scale -> cool white (cream-50 = surface-invert in dark mode) === */
  --color-cream-50:  #fbfcfe;
  --color-cream-100: #eef3fb;

  /* Deep red accent used sparingly -> French Rose for warmth consistency */
  --color-raspberry-700: #c4001d;

  /* === Light-mode canvas: warm cream -> cool white/tints (Alice/Lavender) === */
  --color-surface-brand-primary:   #fbfcfe;
  --color-surface-brand-secondary: #f1f6fd;
  --color-surface-brand-tertiary:  #e7edfb;
}

/* Re-assert dark-mode canvas so the :root overrides above don't leak into dark
   sections (equal specificity, our sheet loads later). Values mirror the base theme's
   originals, which point at the navy scale we've already remapped to Oxford. */
.dark {
  --color-surface-brand-primary:   var(--color-black-strong);
  --color-surface-brand-secondary: var(--color-black-medium);
  --color-surface-brand-tertiary:  var(--color-black-light);
}
/* `lg:dark` is a BREAKPOINT variant — it must only bite from lg up, exactly like the
   Tailwind bundle's own .lg\:dark (which flips the text tokens) does. Listing it
   unwrapped alongside .dark darkened the surfaces at every width: the insights article
   hero is `bg-surface-brand-secondary text-text-primary lg:bg-black lg:dark`, so on a
   phone it took the dark navy surface while the text tokens stayed dark — the title
   was black on navy. Keep this media query in step with the bundle's lg breakpoint. */
@media (min-width: 1024px) {
  .lg\:dark {
    --color-surface-brand-primary:   var(--color-black-strong);
    --color-surface-brand-secondary: var(--color-black-medium);
    --color-surface-brand-tertiary:  var(--color-black-light);
  }
}

/* === Footer (.dc-foot): brand block left · eyebrow link columns right ========
   Fully hand-rolled (the captured Tailwind bundle can't JIT new utilities).
   Structure: gradient hairline top edge → brand/tagline/socials + 3 link
   columns (vertical divider rules between columns on md+, full-height on lg+
   via padding moved off __inner onto the columns) → inline legal bottom row.
   Mobile-first. */
.dc-foot {
  background: var(--color-surface-brand-primary);
  font-family: var(--font-main);
}
.dc-foot__hairline {
  height: 3px;
  background: linear-gradient(90deg, #22d2a2 0%, #1892e5 50%, #0b44cf 100%);
}
.dc-foot__inner {
  padding: clamp(2.5rem, 6vw, 4.5rem) 1rem clamp(1.25rem, 3vw, 2rem);
}
.dc-foot__grid {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}
.dc-foot__cols {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

/* Brand block */
/* Tap targets, here and through the rest of the footer: every control gets a real
   44x44 box. Where that box is bigger than the mark inside it, the extra height is
   padding and a matching negative margin hands it straight back to the layout — the
   target grows, nothing moves. (These links passed WCAG 2.5.8 only via its Spacing
   exception, which quietly evaporates the first time anyone tightens a gap.) */
.dc-foot__logo { display: inline-flex; align-items: center; min-height: 44px; margin-block: -7px; }
.dc-foot__logo img { display: block; height: 1.875rem; width: auto; }
.dc-foot__logo:hover { opacity: 0.8; }
.dc-foot__tag {
  margin: 1rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  letter-spacing: 0.02em;
  color: var(--color-text-tertiary, #56585f);
}
/* Registered office + phone. <address> is the right element for the contact
   details of the page's owner, but its UA italic reads as an aside here, so it is
   reset. The tel links carry the same 44px floor as every other control in this
   footer — a phone number is the one link most likely to be tapped on a phone. */
.dc-foot__addr {
  margin: 0.875rem 0 0;
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 0.8125rem;
  line-height: 1.65;
  letter-spacing: 0.02em;
  color: var(--color-text-tertiary, #56585f);
  max-width: 22rem;
}
.dc-foot__addr-label {
  display: block;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-size: 0.6875rem;
  color: var(--color-text-muted, #9a9ca3);
  margin-bottom: 0.25rem;
}
.dc-foot__addr-tel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 1.25rem;
  /* Same trade as the link columns: the row gap lives inside the links, and the
     negative margin hands the padding back so the block keeps its rhythm. */
  margin-block: -0.5rem;
}
.dc-foot__addr-tel a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--color-text-primary, #011c46);
  transition: color 0.2s ease;
}
.dc-foot__addr-tel a:hover { color: #0b44cf; }

.dc-foot__social {
  display: flex;
  align-items: center;
  /* The 44px boxes below now supply the spacing the gap used to, so the gap goes to
     zero — anything more and the row would outgrow a narrow phone. -12px slides the
     first icon back under the wordmark above it, and the lighter top margin absorbs
     the box's own padding. */
  gap: 0;
  margin-top: 0.75rem;
  margin-left: -12px;
}
.dc-foot__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  color: var(--color-text-muted, #9a9ca3);
  transition: color 0.2s ease;
}
.dc-foot__social a:hover { color: #0b44cf; }
.dc-foot__social svg { width: 1.25rem; height: 1.25rem; }

/* Link columns */
.dc-foot__eyebrow {
  margin: 0 0 1.125rem;
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-text-primary, #011c46);
}
.dc-foot__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* The row gap moves inside each link (min-height below), turning dead space between
     the links into hit area. Row pitch stays ~the same; the target more than doubles. */
  gap: 0;
}
.dc-foot__col a {
  /* inline-flex, not flex: the box grows downward to 44px but keeps its width at the
     text, so the hit area never spreads sideways into the column's empty space. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  /* 44 in both directions — the shortest label here ("AIOps") is only 41px wide. */
  min-width: 44px;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--color-text-primary, #011c46);
  transition: color 0.2s ease;
}
.dc-foot__col a:hover { color: #0b44cf; }

/* Bottom row: copyright + inline legal links */
.dc-foot__bottom {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--color-border-primary, #e3e5e8);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.dc-foot__copy {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted, #9a9ca3);
}
.dc-foot__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 1.5rem;
  /* Same trade as the columns above: the row gap moves inside the links, and the
     negative block margin returns the padding so the bottom bar keeps its height. */
  row-gap: 0;
  margin-block: -0.75rem;
}
.dc-foot__legal a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.8125rem;
  color: var(--color-text-tertiary, #56585f);
  transition: color 0.2s ease;
}
.dc-foot__legal a:hover { color: #0b44cf; }

/* ≥768px: link columns go 3-up (brand still full-width above), with a
   vertical rule between adjacent columns (rules span the columns row) */
@media (min-width: 768px) {
  .dc-foot__inner { padding-left: 1.5rem; padding-right: 1.5rem; }
  .dc-foot__cols { flex-direction: row; gap: 1.5rem; }
  .dc-foot__cols .dc-foot__col { flex: 1; }
  .dc-foot__col + .dc-foot__col {
    border-left: 1px solid var(--color-border-primary, #e3e5e8);
    padding-left: 1.5rem;
  }
  .dc-foot__bottom { flex-direction: row; align-items: center; justify-content: space-between; }
}
/* ≥1024px: brand group left, link-column cluster pushed to the right edge.
   Every column carries a left rule (the first doubles as the brand/columns
   divider). The footer's top/bottom breathing room moves off __inner onto
   the columns as padding so the rules run full height — from the gradient
   hairline down to the legal row's border-top, like the section dividers
   elsewhere on the site. */
@media (min-width: 1024px) {
  .dc-foot__inner { padding-left: 2.5rem; padding-right: 2.5rem; padding-top: 0; }
  .dc-foot__grid { flex-direction: row; justify-content: space-between; gap: clamp(3rem, 5vw, 5rem); }
  .dc-foot__brand { flex-shrink: 0; padding-top: clamp(2.5rem, 6vw, 4.5rem); }
  .dc-foot__cols { gap: clamp(2rem, 3vw, 3.5rem); flex: 1 1 auto; max-width: 68rem; }
  .dc-foot__cols .dc-foot__col {
    flex: 1 1 0;
    min-width: 0;
    border-left: 1px solid var(--color-border-primary, #e3e5e8);
    padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(2.5rem, 5vw, 3.5rem) clamp(1.75rem, 2.5vw, 2.5rem);
  }
  .dc-foot__bottom { margin-top: 0; }
}

/* === Nav "Talk to us" — always brand-filled OFF the homepage ================
   On the homepage the top-right CTA starts plain and the brand gradient rises
   to fill it as you scroll past the hero pill (the scroll-triggered flourish
   in landing-3.css). Everywhere else that animation shouldn't run — the CTA
   should just read as a solid, coloured button from the start.

   This sheet loads last on EVERY page, so it's the one place that reaches the
   CTA even on pages that don't ship landing-3.css (contact, about, careers,
   privacy, terms, whistleblower). We gate on the homepage's pinned hero
   (.dc-hero3 exists only on `/`): every page WITHOUT it gets the static fill,
   while `body:has(.dc-hero3)` keeps landing-3.css's animated behaviour intact.
   The `::before` layer (and its gradient fallback) is redeclared here so it
   works even where landing-3.css is absent. */
body:not(:has(.dc-hero3)) [data-nav-cta] {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: #fff;
  transition: none;
}
body:not(:has(.dc-hero3)) [data-nav-cta]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;                    /* above the cell's own bg, below the label */
  background-image: var(--dc-gradient, linear-gradient(90deg, #22d2a2 0%, #1892e5 50%, #0b44cf 100%));
  clip-path: none;                /* fully filled — no scroll-driven rise */
  transition: none;
}

/* ===========================================================================
   Mobile responsive — cross-cutting foundation
   ---------------------------------------------------------------------------
   Loaded last on EVERY page, so these are the site-wide guards that every
   page inherits. Section-specific mobile composition lives in each section's
   own sheet (landing-3.css, about-team.css, insights.css, …). Blocks 2–4 are
   gated to phone + tablet (≤1023px); block 1 (overflow guard) is site-wide so
   11"/13" laptops (1280/1366/1440) never grow a horizontal scrollbar.
   Primary test widths: 360, 390, 768, 1280, 1366, 1440.
   =========================================================================== */

/* 1 · Horizontal-overflow guard — ALL widths. A single wide element (a
   decorative field, a long unbroken word, an off-canvas animation, a hovered
   edge tile) otherwise scrolls the WHOLE page sideways. `clip` (not `hidden`)
   is deliberate: it stops horizontal scroll WITHOUT establishing a scroll
   container, so `position: sticky` still works — critical for the homepage
   hero pin and the story-scroller pin. Every element that intentionally paints
   wide on desktop (marquees, hero field exit, decor squares, cert wall) sits
   inside its own overflow-hidden ancestor, so clipping at the root is safe. */
html, body { overflow-x: clip; }

/* 2 · Media never forces the page wider than the viewport. `:where()` keeps
   specificity at 0 so any element's own sizing still wins, and the marquee /
   cert / award logos (deliberately pinned to fixed px boxes inside an
   overflow-hidden, max-content track) are excluded so their scroll math holds. */
@media (max-width: 1023px) {
  :where(img, svg, video, canvas, iframe):not(.dc-marquee__track *) {
    max-width: 100%;
  }
}

/* 3 · Long unbreakable strings (URLs, big compound words, emails) wrap instead
   of punching a hole through the layout. Scoped to prose/heading containers.
   Wide rich-text blocks (code, tables — possible in rendered Insights posts)
   scroll inside their own box rather than widening the page. `:where()` keeps
   specificity 0 so any real table/pre styling still wins. */
@media (max-width: 1023px) {
  :where(h1, h2, h3, h4, p, li, figcaption, blockquote) { overflow-wrap: break-word; }
  :where(pre) { max-width: 100%; overflow-x: auto; }
  :where(table) { display: block; max-width: 100%; overflow-x: auto; }
}

/* 4 · Tap targets. Give the button-like pills a ≥44px hit area (most are already
   ~41.6px from their padding; this guarantees the floor). Scoped to genuine
   controls so inline text links are untouched.

   The real buttons carry the floor unconditionally. It used to sit behind
   `(hover: none) and (max-width: 1023px)`, but target size is pointer-agnostic in
   both WCAG 2.5.5 and 2.5.8 — a 41.6px control is undersized for a mouse too, and
   that query also missed touch laptops and anyone dragging a phone-width window on
   a desktop. These four already declare `inline-flex` + `align-items: center`
   themselves, so all this adds is the couple of pixels. */
.dc-cta,
.dc-mh-cta,
.dc-cta-band__btn,
.dc-cta-band .dc-cta,
.dc-h3-cx-btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
/* The two capability-section links stay pointer-scoped. They are text links sitting
   in a copy row, not pills: __cslink aligns its chevron on the text BASELINE (this
   file loads last, so centring it here would silently win) and __cta is plain inline
   with no box of its own. Giving them a 44px box costs ~22px of vertical space in
   the middle of body copy, which is a layout decision for those pages rather than a
   freebie. They clear 24×24 with room to spare, so this is 2.5.5, not a 2.5.8 fail. */
@media (hover: none) and (max-width: 1023px) {
  .dc-capsec__cta,
  .dc-capsec__cslink {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
}

/* ===========================================================================
   Mobile design v2 — "calmer & compact" (phones ≤767px)
   ---------------------------------------------------------------------------
   The mobile pages inherited the desktop composition at a smaller step: large
   headings (display/h1 = 40px, h2 = 28px, h3 = 24px…) crammed into a 16px edge
   gutter. Two global levers here recalibrate the WHOLE site at once (the type
   tokens live in :root; the gutter pattern is shared) — every page inherits it.
   Loaded last, so these win the cascade. Desktop (≥768px) is untouched.
   =========================================================================== */

/* Lever 1 · Calmer mobile type scale. Override the frozen bundle's own
   @media(max-width:768px) :root token step with smaller headings + tight,
   unitless line-heights (so the smaller sizes don't inherit loose desktop
   leading). BODY text is deliberately left at 16px for legibility. Elements
   with an explicit Tailwind leading-* class keep it (--tw-leading wins). */
@media (max-width: 767px) {
  :root {
    --text-display: 2rem;      --text-display--line-height: 1.06;
    --text-h1: 2rem;           --text-h1--line-height: 1.08;
    --text-h2: 1.5rem;         --text-h2--line-height: 1.14;
    --text-h3: 1.3rem;         --text-h3--line-height: 1.18;
    --text-h4: 1.125rem;       --text-h4--line-height: 1.25;
    --text-h5: 1.2rem;         --text-h5--line-height: 1.25;
  }
}

/* Lever 2 · Comfortable gutters. The section-gutter wrappers are exactly the
   elements carrying `px-4` AND `md:px-10` (or the hero copy column's `px-4
   lg:px-10`). Target that pair precisely — 16px → ~22px on phones — so unrelated
   `px-4` uses (cards, buttons, chips) are NOT puffed up. `:where()` keeps
   specificity 0 so any element that needs its own inline padding still wins. */
@media (max-width: 767px) {
  :where(.px-4[class~="md:px-10"], .px-4[class~="lg:px-10"]) {
    padding-inline: 1.375rem;
  }
}

/* === Legal / policy pages (.dc-legal) =======================================
   The four policy pages (/terms/, /privacy/, /whistleblower/, /ethics/) carry
   content imported verbatim from desicrew.in, which uses ordered/unordered
   (and nested) lists the compiled Tailwind bundle has no utilities for. */

/* Policy hero kicker: sized up from the bundle's tiny `text-eyebrow-small`,
   which read as a stray line above a 4.5rem headline. It fades in only after
   the hero title's char reveal (~1s + stagger) has played out. */
.dc-legal-kicker {
  font-size: 0.8125rem;
  line-height: 1.25rem;
  letter-spacing: 0.14em;
}
@media (min-width: 1024px) {
  .dc-legal-kicker {
    font-size: 1rem;
    line-height: 1.5rem;
  }
}
.dc-legal-kicker-row {
  opacity: 0;
  animation: dc-legal-kicker-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) 1.1s forwards;
}
@keyframes dc-legal-kicker-in {
  from { opacity: 0; transform: translateY(0.5rem); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .dc-legal-kicker-row {
    opacity: 1;
    animation: none;
  }
}

.dc-legal ul,
.dc-legal ol {
  margin: 0 0 2.5rem;
  padding-left: 1.5rem;
  display: grid;
  gap: 0.625rem;
}
.dc-legal ul { list-style: disc; }
.dc-legal ol { list-style: decimal; }
.dc-legal li {
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--color-text-primary, #011c46);
}
.dc-legal li::marker { color: var(--color-text-tertiary, #56585f); }
.dc-legal li > ul,
.dc-legal li > ol { margin: 0.625rem 0 0; }
.dc-legal ul ul { list-style: circle; }
.dc-legal a {
  text-decoration: underline;
  font-weight: 600;
}

/* Footer legal row: pipe-separated policy links (Terms | Privacy | …) */
.dc-foot__legal { column-gap: 0.875rem; }
.dc-foot__legal a:not(:first-child)::before {
  content: "|";
  margin-right: 0.875rem;
  color: var(--color-border-primary, #e3e5e8);
}

/* === Legal hero headline (terms / privacy / ethics / whistleblower) ============
   These four pages load ONLY the frozen Tailwind bundle — not landing-3.css — so
   neither `@keyframes dc-fade-in` nor the homepage's `.dc-hero3 .js-title` safety net
   reaches them. Their headline ships with Tailwind's `opacity-0` and is revealed
   purely by the <dc-atom-text-hero-title> controller in the frozen bundle. If that
   controller does not run, the heading stays invisible — permanently, with nothing to
   recover it. That is the one structural difference between these pages and the
   homepage, which has exactly this net.

   Give them their own fade. A CSS animation outranks the controller's inline opacity
   in the cascade, so where the controller DOES run the scramble still plays over the
   top and the two coexist — the same arrangement the homepage already uses.
   dc-section-hero-heditorial appears on those four pages plus /404, and nowhere else.
   404 deliberately reuses this hero for the same reason: it loads only the frozen
   Tailwind bundle, so this fade is the only thing that guarantees its headline shows. */
@keyframes dc-legal-title-in { from { opacity: 0; } to { opacity: 1; } }
dc-section-hero-heditorial .js-title {
  animation: dc-legal-title-in 1s 0.15s ease both;
}
@media (prefers-reduced-motion: reduce) {
  dc-section-hero-heditorial .js-title { animation: none; opacity: 1; }
}
