/* =============================================================================
   KUEC — shared responsive layer (phone + tablet)

   DESKTOP IS DELIBERATELY UNTOUCHED. Every rule in this file lives inside a
   `max-width` media query capped at 1024px, so nothing here can reach a
   >=1025px viewport. Desktop rendering is byte-for-byte what it was before.

   LOAD ORDER MATTERS: this file is linked from each page's <helmet> *before*
   that page's inline <style> block. Same-specificity rules therefore resolve
   in favour of the page, so existing per-page mobile tuning (which is id-based
   and already verified) keeps winning. This file is the baseline that fills the
   gaps — chiefly the tablet range, which had no rules at all.

   Why the attribute selectors: the layouts hardcode 1920-derived values as
   INLINE styles (`padding:0 150px`, `left:max(150px, calc(50vw - 810px))`).
   Those are unreachable from a stylesheet by name because most of the
   containers carry no id or class. `[style*="…"]` + `!important` is the only
   way to taper them without rewriting 42 inline styles across 18 files, and it
   is mechanical enough to survive the WordPress port.

   GOTCHA — match the RENDERED style string, not the authored one. dc-runtime
   hands inline styles to React, which re-serialises them, and the browser then
   normalises the values. What you author is NOT what `[style*=]` sees:
       authored  padding:0 150px 130px
       rendered  padding: 0px 150px 130px          (space added, 0 -> 0px)
       authored  left:max(150px, calc(50vw - 810px))
       rendered  left: max(150px, -810px + 50vw)   (calc() folded away)
   Selectors below carry both spellings: the rendered one does the work, the
   authored one is a fallback for any node the runtime does not manage.
   ========================================================================== */


/* ─────────────────────────────────────────────────────────────────────────
   1. NAVIGATION — burger + slide-down menu up to 1024px

   The desktop mega menu is hover-driven, which is unusable on touch, so the
   whole tablet range gets the burger. `#mobile-menu`'s inline `display` is
   React-driven off `isMobile` (window.innerWidth <= 768), so it computes to
   `none` at tablet — these !important rules override that without touching
   the component state, which stays the single source of truth for open/closed.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
  #nav-links, #nav-cta { display: none !important; }
  #nav-burger { display: flex !important; }
  #mobile-menu { display: flex !important; }

  /* Theme toggle stays in the main navbar (before the burger). Hide the labelled
     duplicate that used to live inside the dropdown. */
  .m-theme-toggle { display: none !important; }

  /* The menu now carries the full pillar tree, so it can outgrow the screen. */
  #mobile-menu {
    max-height: calc(100vh - 58px) !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
  }

  /* Core Pillars accordion — a native <details>, so it needs no component
     state and behaves identically on all 18 pages. */
  .m-dd { width: 100%; }
  .m-dd > summary {
    display: flex; align-items: center; justify-content: space-between;
    padding: 11px 0; font-size: var(--t-body); font-weight: var(--w-body);
    color: rgba(255,255,255,0.92); cursor: pointer;
    list-style: none; user-select: none;
  }
  .m-dd > summary::-webkit-details-marker { display: none; }
  .m-dd > summary::marker { content: ''; }
  .m-dd-arrow { width: 9px; height: auto; display: block; flex-shrink: 0;
                transition: transform 0.25s ease; }
  .m-dd[open] > summary .m-dd-arrow { transform: rotate(180deg); }

  .m-dd-body { padding: 4px 0 10px 2px; }
  .m-dd-group { padding: 10px 0 4px; }
  .m-dd-group + .m-dd-group { border-top: 1px solid rgba(255,255,255,0.07); }
  .m-dd-num { font-size: 11px; font-weight: 400; letter-spacing: 0.4px;
              color: rgba(255,255,255,0.45); margin-bottom: 6px; }
  .m-dd-h { display: block; font-size: var(--t-search); font-weight: var(--w-body); color: #fff;
            line-height: 1.35; margin-bottom: 8px; }
  .m-dd-sub { display: flex; align-items: center; gap: 9px; padding: 7px 0;
              font-size: var(--t-pill); font-weight: var(--w-body); color: rgba(255,255,255,0.88); }
  .m-dd-sub::before { content: ''; width: 3px; height: 3px; border-radius: 50%;
                      background: currentColor; flex-shrink: 0; }

  /* The fixed mega menu must never show while the burger is in play. */
  .nav-dd-menu { display: none !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   2. TABLET (769–1024) — this range previously had NO layout rules at all,
   so every page rendered its 1920px desktop grid into ~834px. Headings wrapped
   to four lines, images clipped, and text columns collapsed to ~250px.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width: 769px) and (max-width: 1024px) {

  /* -- page gutters: 150px is a 1920 value (see CLAUDE.md) ----------------
     `.pg-pad` marks every container whose inline style sets a 150px LEFT/RIGHT
     padding (107 of them across the 18 pages, with 18 different vertical
     values). The class is stamped on by the propagate script precisely so this
     rule does not have to enumerate those spellings — and so the WordPress
     port has one hook to carry over. Only the horizontal padding is touched;
     each container keeps its own vertical rhythm. */
  .pg-pad { padding-left: 40px !important; padding-right: 40px !important; }
  /* :not(...) is load-bearing — `margin-left: max(150px` CONTAINS the substring
     `left: max(150px`, so this selector was also matching about.html's #partner-card
     (whose offset is a margin, not a left) and stamping `left: 24px` on it. That shifted
     the frosted panel 24px right: a strip of the background photo showed down its left
     edge while the panel overhung the right. Attribute substring matching has no word
     boundary, so the longhands have to be excluded explicitly. */
  [style*="left: max(150px"]:not([style*="margin-left: max(150px"]):not([style*="padding-left: max(150px"]),
  [style*="left:max(150px"]:not([style*="margin-left:max(150px"]):not([style*="padding-left:max(150px"])
  { left: 40px !important; }
  [style*="right: max(150px"], [style*="right:max(150px"] { right: 40px !important; }

  /* -- split two-column blocks → single column ---------------------------
     These are the asymmetric image/text splits (44fr 56fr, 30fr 70fr, …).
     Below ~1100px the text column can no longer hold its measured line
     breaks, so stacking is the only thing that keeps them readable. */
  #who-inner, #pillars-inner,
  #pt-s1-inner, #pt-s2-inner,
  #bridge-inner, #focus-inner,
  #ceo-inner, #startup-inner, #subsgrid-inner,
  #c-grid, #form-inner,
  .coe-split-inner, .cp-block-inner, .prog-block-inner, .prog-head {
    grid-template-columns: 1fr !important;
    column-gap: 0 !important;
    row-gap: 34px !important;
  }

  /* The bottom-alignment trick (`margin-top:auto` pinning cards to the image
     base) is meaningless once stacked — it just adds dead space. */
  #bridge-col, #who-col { padding-top: 0 !important; }
  #bridge-inner > div, #who-inner > div { max-width: 100% !important; }

  /* -- 4- and 5-up card rows → 2-up -------------------------------------- */
  .coe-4col, .cp-cards4, .prog-cards, .cp-steps, #reach-grid, #subs-cards {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* -- 3-up card rows → 2-up --------------------------------------------- */
  #facility-grid, #proof-grid, #rel-grid, #reps-grid, #news-grid {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* -- FAQ: the 175px label column starves the question column ----------- */
  #faq-inner {
    grid-template-columns: 1fr !important;
    gap: 28px !important;
    row-gap: 26px !important;
    padding: 48px 24px 72px !important;
  }
  #faq-inner h2 { font-size: 28px !important; }

  /* -- flex heroes: a fixed-width side card (420px + 60px gap) eats the row,
        leaving the headline ~274px, so the H1 broke onto five lines. ------ */
  #cp-hero-inner, #ra-hero-inner {
    flex-direction: column !important;
    align-items: flex-start !important;
    justify-content: flex-end !important;
    gap: 32px !important;
  }
  #cp-hero-card, #ra-hero-card {
    position: static !important; width: 100% !important; flex-shrink: 1 !important;
  }
  /* Once stacked the hero content is taller than the `height:70vh` shell, and
     the section's own `overflow:hidden` (there to crop the backdrop) silently
     cut the card off — 44px of it at iPad landscape 1024x768. Let the section
     grow instead, keeping the 70vh look as a floor. */
  #cp-hero, #ra-hero { height: auto !important; min-height: 70vh !important; }

  /* -- edge-bleed accordion (#pt-acc, 5 pages) ---------------------------
     Its rows escape the panel via negative margins cut to the panel's own
     desktop padding (-92px / -150px). Once .pg-pad tapers that padding to
     40px the bleed overshoots by 110px — the only horizontal overflow the
     tablet pass introduced (996px rows inside an 834px viewport).
     science-technology-park puts the offsets on the ROWS, via a JS style
     object keyed to `isMobile` (which only knows <=768); the other four put
     them on the container inline. This pair covers both spellings.
     Drop the bleed entirely rather than re-cutting it to 40px: the five pages
     disagree about which sides are offset (one sets only margin-left), so a
     blanket -40px pushed the one-sided ones 40px off the other edge. Zeroing
     matches what advanced-facilities-leasing and prototyping-trl-bridge
     already do at their phone breakpoint. */
  #pt-acc { margin-left: 0 !important; margin-right: 0 !important; }
  #pt-acc > div {
    margin-left: 0 !important; margin-right: 0 !important;
    padding-left: 0 !important; padding-right: 0 !important;
  }

  /* Same 1920-cut bleed, but on a horizontal scroller that must keep it, so
     re-cut to 40px instead of dropping it (dropping it would strand the
     first card 40px in from the edge it is meant to run off). */
  .inv-carousel {
    margin-left: -40px !important; margin-right: -40px !important;
    padding-left: 40px !important; padding-right: 40px !important;
    scroll-padding-left: 40px !important;
  }

  /* -- editorial 3-up grids -> 2-up; the featured tile spans the row ------ */
  #blog-grid, #six-grid { grid-template-columns: repeat(2, 1fr) !important; }
  .blog-featured { grid-column: 1 / -1 !important; }
  #six-inner { grid-template-columns: 1fr !important; row-gap: 30px !important; }

  /* -- media that was sized against a 1920 column ------------------------
     `max-width` only — it stops a wide photo overflowing the narrower column
     without ever upscaling. This was originally `width:100%`, which blew up
     every NESTED icon too: core-pillar's `.cp-steps` icons are authored at
     26x26 but sit inside `.cp-block-inner`, so they rendered at 365x365.
     None of these containers has a direct `img` child, so a `>` combinator
     can't separate section photos from icons — don't reach for `width` here. */
  #bridge-inner img, #who-inner img, .prog-block-inner img,
  .coe-split-inner img, .cp-block-inner img {
    max-width: 100% !important;
  }

  /* -- footer: 35fr leaves the frosted panel ~292px, far too narrow for its
        two-column link grid, so stack it exactly like the phone layout. --- */
  #footer-section { min-height: 0 !important; }
  #footer-grid { grid-template-columns: 1fr !important; min-height: 0 !important; }
  /* index.html's footer is a Bootstrap flex row (`.row.g-0`) rather than a
     grid, so the grid rule above is inert there — stack it on the flex axis
     and release the 35%/65% basis. Harmless on the grid-based pages. */
  #footer-grid { flex-direction: column !important; }
  #footer-left, #footer-right {
    flex: 0 0 auto !important; max-width: 100% !important; width: 100% !important;
  }
  #footer-right { order: 1 !important; }
  /* Two ids to outrank each page's own `#footer-left { padding:60px 40px 60px 80px }`,
     which lives in a 769-1199 query and loads after this file. That 80px left
     inset is a DESKTOP value — it indents the frosted panel's text while the
     panel sits in the 35% column. Once the footer stacks, it just knocks the
     info panel 40px out of line with the subscribe form above it. Left alone
     above 1024, where the two-column footer is still in play. */
  #footer-grid #footer-left { order: 2 !important; padding: 48px 40px !important; }
  #footer-right-inner { position: static !important; align-items: flex-start !important;
                        padding: 56px 40px 48px !important; }
  #footer-right-inner h2, #footer-right-inner p { text-align: left !important; }
  /* index.html's right column is anonymous — same fix, see the phone block. */
  #footer-right > div:not([id]) {
    position: static !important; align-items: flex-start !important;
    padding: 56px 40px 48px !important;
  }
  #footer-right > div:not([id]) h2,
  #footer-right > div:not([id]) p { text-align: left !important; }
  #footer-frost { display: none !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   3. PHONE (<= 768) — safety net.
   Most pages already carry hand-tuned id-based mobile rules; those are more
   specific and still win. What follows only catches what nothing else covers,
   chiefly the unnamed inner containers that kept their 150px side padding.
   (index.html's hero was the worst case: 430px viewport → 82px of content.)
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .pg-pad { padding-left: 24px !important; padding-right: 24px !important; }
  /* See the tablet rule above: exclude margin-left / padding-left, which contain this
     substring and were being given a `left` offset they never asked for. */
  [style*="left: max(150px"]:not([style*="margin-left: max(150px"]):not([style*="padding-left: max(150px"]),
  [style*="left:max(150px"]:not([style*="margin-left:max(150px"]):not([style*="padding-left:max(150px"])
  { left: 24px !important; }
  [style*="right: max(150px"], [style*="right:max(150px"] { right: 24px !important; }

  /* Any remaining desktop multi-column grid collapses. Attribute selectors
     (0,1,0) sit below the pages' id rules, so tuned pages are unaffected. */
  [style*="grid-template-columns: repeat(2"],
  [style*="grid-template-columns: repeat(3"],
  [style*="grid-template-columns: repeat(4"],
  [style*="grid-template-columns: repeat(5"],
  [style*="grid-template-columns:repeat(2"],
  [style*="grid-template-columns:repeat(3"],
  [style*="grid-template-columns:repeat(4"],
  [style*="grid-template-columns:repeat(5"] {
    grid-template-columns: 1fr !important;
  }

  /* -- home / shared footer ------------------------------------------------
     Stack the 35/65 grid on phones. #footer-right-inner used to be anonymous on
     index and targeted via `:not([id])`; shared footer.php now gives it an id,
     so un-absolute it explicitly. */
  #footer-section { min-height: 0 !important; }
  #footer-grid {
    grid-template-columns: 1fr !important;
    min-height: 0 !important;
  }
  #footer-left, #footer-right {
    flex: 0 0 auto !important;
    max-width: 100% !important;
    width: 100% !important;
  }
  #footer-right { order: 1 !important; }
  #footer-left  { order: 2 !important; }
  #footer-right-inner {
    position: static !important;
    align-items: flex-start !important;
    justify-content: flex-start !important;
    padding: 44px 24px 40px !important;
  }
  #footer-right-inner h2,
  #footer-right-inner p { text-align: left !important; }
  #footer-right-inner h2 br { display: none !important; }
  #footer-right-inner > div { max-width: 100% !important; }
  #footer-right > div:not([id]) {
    position: static !important;
    align-items: flex-start !important;
    padding: 44px 0 40px !important;
  }
  #footer-right > div:not([id]) h2,
  #footer-right > div:not([id]) p { text-align: left !important; }

  /* No 3D torus (or still stand-in) on phones — keep the footer photo clean. */
  #footer-torus { display: none !important; }

  /* Core pillar hero tints — mobile left-to-right scrim (matches prototyping-trl-bridge.php). */
  #ra-hero-tint,
  #prog-hero-tint,
  #subs-hero-tint,
  #cp-hero-tint {
    background-image: linear-gradient(to right, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.58) 45%, rgba(0,0,0,0.28) 100%) !important;
    background-color: rgba(0, 0, 0, 0.2) !important;
  }

  /* Hide hero "What's on this page" TOC cards on phones — sections are reachable by scroll. */
  #page-toc,
  #inv-toc,
  #sci-toc,
  #coe-toc,
  #ip-toc,
  #cp-hero-card {
    display: none !important;
  }

  /* -- pill buttons ------------------------------------------------------
     These are authored at a fixed `height:40px`. That is fine while the label
     is one line, but at phone width "Explore Our Core Pillars" wraps to two
     and the text spilled straight out of the pill. Auto height with a 40px
     floor leaves every single-line button pixel-identical. */
  #hero-content .btn-gradient,
  #hero-content .btn-solid,
  #hero-content .btn-white,
  .acc-explore,
  #footer-right .btn-gradient,
  #footer-right .btn-solid,
  #footer-right .btn-white,
  #mobile-menu .m-nav-cta {
    height: auto !important;
    min-height: 40px !important;
    padding-top: 10px !important;
    padding-bottom: 10px !important;
    line-height: 1.3 !important;
    white-space: normal !important;
  }
  #hero-cta-row { flex-wrap: wrap !important; }

  /* Section header rows (heading block + trailing CTA) laid out as a
     space-between flex row. The equivalent rows on the other pages carry ids
     and are already stacked by their own phone rules; core-pillar's two were
     anonymous, so they stayed side by side and squeezed the heading to 144px.
     `.hdr-row` is stamped on by the propagate script to give them a handle. */
  .hdr-row {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 18px !important;
  }

  /* Nothing may introduce a horizontal scrollbar on a phone.

     BODY ONLY — do NOT add `html` back to this selector. When html's overflow is `visible`,
     the UA propagates BODY's overflow-x to the viewport and body itself resolves to visible,
     so the phone gets its horizontal clip and body is not a scroll container. Setting
     overflow-x on html instead consumes the propagation, body keeps its own value, and
     `overflow-x:hidden` + `overflow-y:visible` promotes body to a SCROLL CONTAINER. Every
     `position:sticky` element then resolves against body's scrollport — which never scrolls,
     html does — so it silently stops pinning and just scrolls away. That is exactly what
     broke programs.html's #prognav strip on phones while it worked fine on desktop. */
  body { max-width: 100% !important; overflow-x: hidden !important; }
}


/* ─────────────────────────────────────────────────────────────────────────
   4. ORBS + DECORATIVE GLOWS

   orb-effect.js already self-removes at <=768 (connectedCallback bails before
   creating a WebGL context), so the phone rules below govern the CSS radial
   *fill* that stays behind as the stand-in — those fills are positioned for a
   1920 canvas and drift badly once the layout stacks.

   Tablet keeps the live orb: it is one canvas, the fills are percentage-based
   and so still track their section, and the glow reads as intended at 834px.
   ───────────────────────────────────────────────────────────────────────── */
/* Keep the colour fills ROUND.

   `radial-gradient(ellipse A% B% …)` sizes its two radii against the BOX, so
   the blob's shape is the box's aspect ratio. Every fill was measured against
   a WIDE desktop box; on a phone that same box turns tall and narrow — index's
   accordion goes 1140x820 (aspect 1.39) to 380x698 (aspect 0.55) — and the
   blob smears vertically. Measured: 106px wide by 279px tall, a 2.6:1 smear
   that reads as a hard purple band down one side rather than a glow. Tablet is
   just as bad (754x900 gives a 422x720 blob).

   This is the whole effect on a phone: orb-effect.js self-removes at <=768, so
   there is no canvas left to carry it.

   Fix the BOX aspect rather than rewriting the gradients — for `ellipse A% B%`
   the blob is round when boxW/boxH == B/A. Every measured colour stop then
   stays exactly as authored (see CLAUDE.md on how those alphas were derived).
   Each gradient's last stop is already alpha 0, so the enlarged box introduces
   no hard edge even where it overhangs its section.

   KEEP THE FILL CONCENTRIC WITH THE ORB. Where the ring and the colour fill are
   separate elements, the fill IS the visible blob and the orb only supplies the
   ring underneath — so moving one without the other reads as "the purple isn't
   centred on the orb". Every override below therefore preserves the authored
   blob CENTRE and changes only the box's aspect. */
@media (max-width: 1024px) {
  #accordion-orb-fill, #c-orb-fill, #c-orb2-fill, #model-glow {
    inset: auto !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
    height: auto !important;
  }
  /* ellipse 28% 40% -> 40/28. `left:50%` + `width:104%` puts the gradient's own
     `at 64%` back at 64.6% of the container — i.e. still concentric with the orb
     wrapper, which spans 14%..114% precisely to centre on that 64%. */
  #accordion-orb-fill { top: 47% !important; width: 104% !important; aspect-ratio: 1.43 !important; }
  /* ellipse 40% 40% at 50% 50% -> square box, centre unmoved. */
  #c-orb-fill, #c-orb2-fill { top: 50% !important; width: 104% !important; aspect-ratio: 1 !important; }
  /* ellipse 50% 46% at 50% 50% -> 46/50, centre unmoved. */
  #model-glow { top: 50% !important; width: 116% !important; aspect-ratio: 0.92 !important; }
  /* #prog-orb-fill is deliberately NOT corrected. Its bright purple layer is
     already `radial-gradient(circle at 27% 20%, …)` — circles are immune to box
     aspect — and only the dim blue wash under it is an ellipse. Deriving the
     height to fix that wash moved the blob 94px up (measured dy -246 authored
     vs -323), sliding it off #prog-orb's ring for no visible gain. */
}
@media (max-width: 768px) {
  /* Orb is gone at this width, so there is no ring to stay concentric with —
     free to centre the blob under the now full-width panels. */
  #accordion-orb-fill { left: 36% !important; }
}
/* Keep the orb HOSTS square-ish too.

   Most glow divs are sized `width:40%; height:78%` against their section. Once
   the tablet rules stack a section, its height roughly doubles while its width
   is capped — so those boxes turn into tall slivers. Measured at 834:
   `.cp-glow` 334x2826 (aspect 0.12), `#subsgrid-glow` 334x985, `#focus-glow`
   334x921, `#ip-s1-glow` 484x1181, `#whopillars-orb` 434x1000.

   That wrecks BOTH layers: the CSS gradient smears, and — because these divs
   also contain the `.orb-layer` — the WebGL canvas is allocated at the same
   sliver aspect, which is why the orb itself "isn't showing properly" on
   tablet. Squaring the host fixes both at once.

   ONLY single elements that carry BOTH the orb and its gradient are listed, so
   squaring them keeps the two inherently concentric. `#prog-orb` and
   `#whopillars-orb` are deliberately excluded: each has its colour fill as a
   SEPARATE sibling, so resizing the ring alone would slide it off the blob —
   a mildly non-square ring reads far better than an off-centre one. They sit
   at 0.43 / 0.49 on tablet, which ovalises the ring slightly; that is the
   accepted trade, and at <=768 they carry no canvas at all so it is moot.
   contact's
   `#c-orb`/`#c-orb2` are excluded too, their fixed-height wrapper being
   load-bearing (see CLAUDE.md on never resizing an orb container at runtime). */
@media (max-width: 1024px) {
  #subsgrid-glow, .cp-glow, #focus-glow, #ip-s1-glow, .coe-glow {
    height: auto !important;
    aspect-ratio: 1 !important;
  }
}

/* PHONE STAND-IN = a rendered image of the orb, not a CSS gradient.

   The WebGL orb stays off at <=768 (orb-effect.js self-removes before creating
   a context — that battery decision is unchanged). The flat radial gradient it
   used to leave behind read as a faint haze rather than an orb, so every glow
   swaps to `uploads/orb-ball.png` here: a violet-to-blue ball with soft alpha
   edges, exported from the design. (Source was a 1065x1210 / 1.35MB PNG — far
   too heavy to push at phones for decoration. Downscaled to 800px and saved as
   WebP: 230KB, an 83% cut, and invisible on a soft gradient with no detail.)

   `background-size: contain` is the important part — it fits the ball inside
   the box WITHOUT distorting it, which makes the whole box-aspect problem moot
   at this width (a stretched box now just yields a smaller centred ball, never
   an oval one). The `aspect-ratio: 1` below is therefore only about giving the
   ball room to be a decent size, not about keeping it round.

   Tablet is deliberately excluded: the real orb renders there, and these
   gradients are its measured colour fill. */
@media (max-width: 768px) {
  #accordion-orb-fill, #prog-orb-fill, #whopillars-glow, #pillars-glow, #ins-hero-fill,
  #c-orb-fill, #c-orb2-fill,
  #why-glow, #subsgrid-glow, #reps-glow, #model-glow, #ip-s1-glow,
  #ip-hero-glow, #focus-glow, #art-glow, #agx-junction-glow, #partner-glow,
  .coe-glow, .cp-glow {
    background-image: url('uploads/orb-ball.webp') !important;
    background-size: contain !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    height: auto !important;
    aspect-ratio: 1 !important;
  }

  /* Belt and braces — the element self-removes, but the blurred wrapper can
     survive as an empty 52px-blur layer on pages that never hid it. */
  .orb-layer { display: none !important; }

  /* A decorative layer must never widen the document. Several glows use
     negative offsets (left:-8%, right:-6%) that `body{overflow-x:hidden}`
     alone does not contain (see CLAUDE.md on #agx-junction-glow). */
  #agx-radial, #portfolio-radial, #subs-wash, #agx-wash {
    overflow-x: clip !important; overflow-clip-margin: 120px !important;
  }

  /* ─────────────────────────────────────────────────────────────────────
     MINIMUM TYPE SIZE ON PHONES — nothing below 14px, except step numbers
     (01, 02, …) which stay at 12px.

     The design's small type (11px eyebrows, 12px captions, 13px footer copy)
     was measured off the 1920 mockups and is fine on a desktop; on a phone it
     is simply too small to read. Desktop and tablet are untouched — this whole
     block is inside the <=768 query.

     WHY ATTRIBUTE SELECTORS: these sizes are authored as INLINE styles on
     hundreds of elements across 18 pages, most of which carry no id or class,
     so there is nothing else to hook. Match the RENDERED declaration, not the
     authored one — dc-runtime hands inline styles to React which re-serialises
     them, so `font-size:11px` reaches the DOM as `font-size: 11px` (see the
     GOTCHA at the top of this file). The full set of sub-14px values in the
     source is 10 / 11 / 11.5 / 12 / 12.5 / 13 / 13.5 plus two clamps.

     `!important` is what makes this beat the inline styles; specificity is
     irrelevant against those. It does NOT beat a page rule that is itself
     `!important`, so the two that existed (programs' .prog-card p at 13.5px,
     index's .prog-chip at 12px) were raised at source instead. */
  [style*="font-size: 10px"],   [style*="font-size: 11px"],
  [style*="font-size: 11.5px"], [style*="font-size: 12px"],
  [style*="font-size: 12.5px"], [style*="font-size: 13px"],
  [style*="font-size: 13.5px"],
  [style*="font-size: clamp(8.58px"],
  [style*="font-size: clamp(12px, 0.73vw, 14px)"],
  .m-dd-sub, .cf-label, .bc-item, .nav-link {
    font-size: 14px !important;
  }

  /* Breadcrumb current-page label stays compact — the 14px floor above would
     otherwise inflate the single mobile crumb (parent crumbs are already hidden). */
  #ra-breadcrumb-inner > span,
  #prog-breadcrumb-inner > span {
    font-size: 12px !important;
  }

  /* ── Card rows become swipeable carousels ──
     Marked containers (see mobile-carousel.js for the dots half) turn from a
     1-up stack into a horizontal scroll-snap track, one card per view. Stacking
     4–9 full-width cards made these sections enormous to scroll past on a phone;
     as a carousel each section is one card tall.

     `!important` because every one of these grids sets grid-template-columns
     inline and most are re-declared in their page's own phone block. min-width:0
     on the slides matters — as flex items they would otherwise size to content
     and overflow the viewport.

     Phone only. Above 768 the containers stay exactly the grids they were, and
     the script strips the dots back out. */
  [data-mob-carousel] {
    display: flex !important;
    grid-template-columns: none !important;
    gap: 12px !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  [data-mob-carousel]::-webkit-scrollbar { display: none; }
  [data-mob-carousel] > * {
    flex: 0 0 100% !important;
    min-width: 0 !important;
    scroll-snap-align: start;
  }
  [data-mob-dots] {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin: 20px 0 4px;
  }
  [data-mob-dots] > span {
    width: 7px; height: 7px; border-radius: 50%; background: #fff;
    opacity: 0.3; transition: opacity 0.25s ease; cursor: pointer;
  }

  /* ── Icon → title spacing in the purple/dark feature cards ──
     `.p-card` and `.inv-res-card` are `display:flex; flex-direction:column;
     justify-content:space-between` with an icon, then a title+copy block. On a
     desktop-width card the min-height leaves slack for space-between to push
     the two apart; on a phone the card collapses to its own content, there is
     no slack left to distribute, and the title ends up sitting directly on the
     icon (measured: a 0px gap on 38 cards across five pages).
     Give the icon its own margin so the spacing does not depend on leftover
     height. 28px matches what intellectual-property's #ip-s2-cards already
     uses, and core-pillar's .cp-purplecard lands at 27px on its own.
     Phone only — above 768 the cards keep their min-height and space-between
     is doing the right thing. */
  .p-card > img, .inv-res-card > img, .accent-card > img { margin-bottom: 28px !important; }

  /* …and the numbers back down to 12px. Listed AFTER the floor above so the
     equal-specificity ones (.m-dd-num) win on order, and every selector here
     resolves to the number element specifically, never its sibling label. */
  .m-dd-num, .nav-mega-num, .prog-num,
  #pt-acc > div > div > span:first-child,
  .ip-step-num,
  .cp-steps > div > span,
  #focus-cards > div > span:first-child,
  #prognav-inner .prognav-item > span:nth-of-type(2),
  /* :first-child matters — the runtime wraps `{{ t.label }}` in its own <span class="sc-interp">,
     so a bare `a > span` also caught the LABEL and shrank it to 12px. */
  #sci-toc a > span:first-child, #coe-toc a > span:first-child, #inv-toc a > span:first-child,
  .inq-head > span:first-child {
    font-size: 12px !important;
  }
}
