/* ==========================================================================
   vedika-page-field.css — lets ONE page-level dust field read through every
   widget on the page.

   WHY THIS FILE EXISTS
   The field created by mountPageField() is position:fixed, inset:0, z-index:0,
   first child of <body>. Nothing about it is subtle — it is a full-viewport
   WebGL canvas. It was still invisible on every page it was added to, because
   these pages are built as `<body class="bg-gray-50">` with a stack of
   `<section class="py-20 bg-white">`, and an opaque ground painted ON TOP of a
   z-index:0 layer covers it completely. So the field is not the work; making
   the existing surfaces translucent is the work.

   ARCHITECTURE, and it is the only one that performs
   One field per page, and widgets are GLASS over it. The alternative — a
   gradient per card — was measured: a static bloom is free, but a drifting one
   costs about 12.9ms per instance, so four of them eat a 60fps budget on their
   own. A page with 40 widgets cannot each own a moving gradient. They share
   one, by being see-through.

   SPECIFICITY, deliberately without !important
   This file loads after tailwind.min.css and is UNLAYERED. Tailwind's `.bg-white`
   is a single class (0,1,0); `section.bg-white` is (0,1,1) and wins on its own.
   That matters because `!important` INVERTS @layer precedence in this codebase
   and has caused real regressions here — dashboard-theme.css is unlayered
   `!important` by design and silently killed --lift and --tray until
   :not() exclusions were added. Nothing here needs that hammer.

   WHAT IS DELIBERATELY NOT TOUCHED
   - Sticky navs and drawers. They overlay reading matter and must stay opaque
     or the text behind them shows through the header.
   - Dark and coloured hero sections. They carry white text; making them
     translucent over a light field would destroy the contrast outright.
   - Anything already carrying its own sheet (.vds-bloom, [data-vedika-sheet]).
   ========================================================================== */

/* --- 1. get the body out of the way -------------------------------------
   The field is behind body content, so any body-level ground hides it. These
   are the grounds Tailwind pages actually use. `background-image:none` is
   here too: `bg-gradient-to-*` on <body> paints an image, not a colour, and
   clearing only background-color would leave it. */
body.vedika-field-on,
body.vedika-field-on.bg-white,
body.vedika-field-on.bg-gray-50,
body.vedika-field-on.bg-gray-100,
body.vedika-field-on.bg-slate-50 {
  background-color: transparent;
  background-image: none;
}

/* --- 1b. content sits above the field, and NO RULE HERE DOES IT ------------
   There is deliberately no lift rule in this file. That is the fix, not an
   omission, so the deleted rule is recorded here rather than in a commit
   message nobody reads next to the CSS.

   What used to be here:

     body.vedika-field-on > *:not(.vedika-page-field) {
       position: relative;
       z-index: 1;
     }

   It was written for a real problem - a z-index:0 field can be painted over by
   in-flow content that creates no stacking context - but `position` is the
   wrong lever, because that selector is (0,2,1) and therefore outranks the
   position every direct child of <body> declares for itself. It did not lift
   those elements. It REWROTE them, and a growing :not() list was the only
   defence. Measured on faq.html at 1440x950, all three at once:

     nav.sticky.top-0            position:sticky -> relative   (stopped sticking)
     aside#faq-mobile-drawer     position:fixed  -> relative   (h=445 IN FLOW)
     .vedika-widget-container    position:fixed  -> relative   (w=1424, after
                                                                the footer)

   The drawer is the expensive one. It is an off-canvas panel held off screen by
   `transform: translateX(-100%)`, which moves paint but not layout, so once it
   was back in flow it reserved a full 445px band between the nav (ends y=72)
   and <main> (started y=517). That band is the empty gradient area in the
   founder's screenshot. Page height 5519 -> 5074 on removal: 445px, exactly.

   THE REPLACEMENT IS z-index:-1 ON THE FIELD, set by vedika-page-field-boot.js
   where the host is created. A fixed element at negative z-index paints after
   the canvas background but before in-flow block backgrounds, so ordinary
   content is above the field with no declaration at all, and nothing anywhere
   on the page has its `position` taken away from it.

   The one thing negative z-index could have broken is the field itself, since
   <body> computes an opaque rgb(233,236,242) on these pages. Measured, and it
   does not: a fixed 70x700 gutter crop compressed to 38,110 bytes before and
   38,148 bytes after, against 946 bytes with the host removed entirely. The
   dust reads through.

   `isolation: isolate` was the other candidate and is wrong: it makes each body
   child a stacking context, so the drawer's own z-index:50 would stop
   outranking <main> and an opened drawer would render underneath the page.

   If some future element really does paint under the field, give THAT element
   a stacking context. Do not reintroduce a rule that reaches every child of
   <body>. */

/* ADDITIVE ONLY, and that is a correctness requirement rather than a style.
   The first version of this file softened broadly and then tried to protect
   dark and gradient surfaces with `background-color: revert`. That is wrong,
   and it was measured wrong: `revert` rolls a property back to the previous
   ORIGIN — the user-agent stylesheet, where background-color is transparent —
   it does NOT restore the author-level Tailwind declaration. So every "hands
   off" guard was stripping the background it was written to preserve. On the
   pilot page that took "Contact Sales" to 1.03:1 and the "cURL Example" label
   from 2.94 to 1.27, i.e. the guards caused the failures.
   (`revert-layer` would not have helped either: Tailwind is unlayered here.)

   The rule that follows from that: every selector below must EXCLUDE what it
   must not touch, so there is never anything to undo. Nothing in this file
   reverts.

   The exclusions, each load-bearing:
     :not([class*="gradient"])  a gradient ground carries white type
     :not([class*="text-white"]) explicit white type
     -500..-900                 saturated Tailwind grounds carry white type
   Shade 50-100 tints are safe: they carry dark type, like the white they
   replace. */

/* --- 2. section grounds become translucent ------------------------------
   Only <section>, and only the light grounds. A section is a page band; a div
   is a widget, and widgets are handled separately below at a higher opacity
   because they carry body copy.

   0.55 was chosen by measurement, not feel: it is the highest transparency at
   which every text run on the pilot page still cleared its WCAG AA
   requirement against the darkest ground the lavender field produces. */
body.vedika-field-on section.bg-white:not([class*="gradient"]):not([class*="text-white"]),
body.vedika-field-on section.bg-gray-50:not([class*="gradient"]):not([class*="text-white"]),
body.vedika-field-on section.bg-gray-100:not([class*="gradient"]):not([class*="text-white"]),
body.vedika-field-on section.bg-slate-50:not([class*="gradient"]):not([class*="text-white"]) {
  background-color: rgba(255, 255, 255, 0.55);
}

/* Some pages band with <div> instead of <section>. Same treatment, but only
   when the div is a full-width band rather than a card — a card has a radius,
   a band does not. This is the cheapest reliable discriminator available in
   CSS and it is why the rule is written negatively. */
body.vedika-field-on > div.bg-white:not([class*="rounded"]):not([class*="gradient"]):not([class*="text-white"]),
body.vedika-field-on > div.bg-gray-50:not([class*="rounded"]):not([class*="gradient"]):not([class*="text-white"]) {
  background-color: rgba(255, 255, 255, 0.55);
}

/* --- 3. widgets become glass -------------------------------------------
   THIS is the founder's ask: the background sheet of each widget carries the
   dusty gradient shade. It carries it by being see-through onto the one field,
   not by owning a gradient.

   0.72 rather than the 0.55 used for bands. A widget is where the body copy
   lives, so it needs the higher floor; a band is mostly empty space between
   widgets, so it can afford to show more field. The saturate() is the same
   trick login.html uses: pushing saturation UP while opacity rises keeps the
   colour reading as colour instead of averaging toward grey behind the veil.
   Opacity is the brightness dial and saturation is the clarity dial, and they
   are independent — that was established on the login sheet, where fill 0.88
   with saturate 3.6 raised pure-white area 10.8% -> 44.9% AND saturation p95
   0.565 -> 0.692 at the same time.

   Scoped INSIDE <section>/<main> on purpose. A rounded white pill in a <nav>
   or a <footer> is a button on chrome, not a widget on the page ground, and
   softening those is exactly what newly broke "Docs", "API Reference" and
   "Contact Sales" on the pilot. Restricting the ancestor is more reliable than
   trying to negate one, which CSS cannot do. */
body.vedika-field-on :is(section, main) [class*="rounded"].bg-white:not([class*="gradient"]):not([class*="text-white"]):not(a):not(button),
body.vedika-field-on :is(section, main) [class*="rounded"].bg-gray-50:not([class*="gradient"]):not([class*="text-white"]):not(a):not(button),
body.vedika-field-on :is(section, main) [class*="rounded"].bg-slate-50:not([class*="gradient"]):not([class*="text-white"]):not(a):not(button) {
  background-color: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(7px) saturate(1.6);
  backdrop-filter: blur(7px) saturate(1.6);
}

/* Tables and code blocks keep a harder floor. Monospace at small sizes is the
   first thing to become unreadable over a moving ground, and a table's zebra
   striping stops being legible as striping once both bands are translucent. */
body.vedika-field-on pre,
body.vedika-field-on code,
body.vedika-field-on table,
body.vedika-field-on thead,
body.vedika-field-on tbody tr {
  background-color: rgba(255, 255, 255, 0.94);
}
body.vedika-field-on pre,
body.vedika-field-on pre code {
  background-color: rgba(17, 20, 34, 0.96);   /* dark code wells stay dark */

  /* A RULE THAT IMPOSES A BACKGROUND OWNS THE TEXT COLOUR THAT GOES ON IT.
   *
   * The line above darkened the well and left the ink to the page, and the
   * page's ink is black. Swept across the 106 pages that load this file, at
   * 1440 and 390: 44 <pre> blocks rendering rgb(0,0,0) on rgb(17,20,34) -
   * 1.15:1 - spread over ~20 API pages (astrology-api-for-apps,
   * birth-chart-calculator-api, crystals-api, dasha-api, jaimini-api,
   * lalkitab-api, panchang-api-for-developers and the rest), plus 12 more at
   * 1.09:1 carrying rgb(22,17,42) - the page's own dark ink - on the same
   * dark well. Those are curl and JSON samples on customer-facing API pages,
   * invisible.
   *
   * CORRECTION (2026-07-31): this note previously blamed those 12 on
   * `text-green-400` being dropped by the purge. That was wrong and is worth
   * recording rather than deleting, because the wrong cause would have sent
   * the next reader to rebuild Tailwind for nothing. `.text-green-400` IS
   * present in the prebuilt css/tailwind.min.css and does paint. The reason
   * the green does not show HERE is this very rule: `body.vedika-field-on pre
   * code` is (0,1,2) and the utility is (0,1,0), so the `color` below wins.
   * That is the intended outcome - #f4f2fb is legible and green-400 on this
   * well would also have been - but it is a specificity result, not a purge.
   *
   * Setting `color` here fixes all of them at once, and it is the correct
   * place: this stylesheet is the thing that made the surface dark, so it is
   * the thing that owes it a readable foreground. Note this cannot be done
   * with a token - --vds-text-primary and --vds-text-inverse both FLIP with
   * the theme while this background does not, so either one reintroduces the
   * same defect in the opposite theme. #f4f2fb is --vds-d-text's literal
   * value, declared once in the base :root and never re-declared per theme.
   * 16.5:1 against rgb(17,20,34).
   *
   * Inheritance makes this safe for highlighted code: a <span class="kw"> or
   * .str that declares its own colour keeps it, because this only reaches text
   * that had no colour of its own - which is exactly the text that was
   * defaulting to black. */
  color: #f4f2fb;
}

/* The `code` in the group at the top of this section is unqualified, so it
   paints white paper on EVERY inline <code> on the page - including one that
   the author already sat inside a dark well. The rule below it only rescues a
   <code> inside a <pre>. A bare <code> in a dark div falls between the two: it
   gets white paper stamped over the well while its own light ink survives.

   Measured at 1440 across all 123 pages: 8 such elements, all on widget.html
   and badge.html, all `<div class="bg-gray-900"><code class="text-green-400">`
   - the embed snippets those two pages exist to hand out. rgb(74,222,128) on
   the 0.94-alpha white composited over the well reads rgb(241,241,242): 1.54:1.
   Blank boxes where the copy-paste code should be.

   The obvious fix - stop papering any <code> in a dark well - is WRONG, and
   the scan is what says so. Of the 101 bare <code> elements sitting in a dark
   well, 67 carry rgb(82,82,91) and 2 carry rgb(22,17,42): dark ink that is
   legible precisely BECAUSE of the white paper. Dropping the paper wholesale
   would break 69 elements to repair 8.

   So qualify on the ink, not the well. Requiring an explicitly light text
   utility on the <code> itself makes the rule safe by construction - no
   dark-ink element can match it, whatever its container. Restores the authored
   terminal: rgb(74,222,128) on rgb(17,24,39) is 10.1:1.

   Harmless where a `pre code` also matches (several API pages nest one inside
   .bg-gray-900): this wins the background, the <pre>'s own rgba(17,20,34,0.96)
   shows through instead, and the `color` above still wins the ink. Same
   pixels, verified in the re-sweep. */
body.vedika-field-on :is([class*="bg-gray-9"], [class*="bg-gray-8"],
                         [class*="bg-slate-9"], [class*="bg-zinc-9"],
                         [class*="bg-neutral-9"], [class*="bg-black"])
  :is(code[class*="text-green-4"], code[class*="text-emerald-4"]),

/* ...and the same thing again for the case where the light ink is declared on
   the WELL and merely inherited by the <code>. free-astrology-api.html writes
   `<div class="bg-gray-900 text-green-400"><code class="text-sm">`, so the
   <code> carries no colour utility at all and the selector above cannot see it.
   Six curl samples, the ones the free-sandbox page exists to show, at the same
   1.54:1.

   Requiring BOTH the dark background and the light ink on ONE element keeps the
   safety property intact: an element that declares `text-green-400` on itself
   has light descendants by construction, so nothing dark-inked can match. The
   looser `[class*="text-green-4"] code` would also have worked here and is not
   used deliberately - a section-level ink class would then reach every <code>
   below it, including ones sitting on light cards. */
body.vedika-field-on :is([class*="bg-gray-9"], [class*="bg-gray-8"],
                         [class*="bg-slate-9"], [class*="bg-zinc-9"],
                         [class*="bg-neutral-9"], [class*="bg-black"]):is(
                         [class*="text-green-4"], [class*="text-emerald-4"])
  code {
  background-color: transparent;
}

/* --- 4. hands off -------------------------------------------------------
   There is deliberately NO rule here.

   This is where the `revert` block used to be, and deleting it is the fix
   rather than a simplification. Overlays (nav, header, sticky, drawers,
   dialogs), saturated and gradient grounds, white type, and surfaces that
   already own their own sheet are all handled by NOT BEING SELECTED in
   sections 1-3 — via the :not() exclusions and the :is(section, main)
   ancestor scope. A stylesheet that never softens them needs no rule to
   un-soften them, and cannot get that rule wrong.

   If a future page needs a surface protected, add the exclusion to the
   softening selector. Do not add an undo rule here. */

/* --- 5. no-WebGL and reduced-motion floors -----------------------------
   If the field never mounts, every rule above has made the page MORE
   transparent over nothing. The class is added by script only after the sheet
   reports it is live, so the selectors simply do not match otherwise; this
   block is the belt-and-braces case where the context is lost after mount. */
body.vedika-field-on.vedika-field-lost section[class*="bg-"],
body.vedika-field-on.vedika-field-lost [class*="rounded"][class*="bg-"] {
  background-color: #fff;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

@media (prefers-reduced-motion: reduce) {
  /* The field still paints, it just stops drifting — that is handled in the
     engine. Nothing to soften differently here; kept as an explicit no-op so
     the next person does not add a rule that fights the engine's own guard. */
  body.vedika-field-on { }
}
