/* ============================================================================
 * premium-enhance.css  —  v1.22.33  (Stage A + B + C + D + E folded in)
 * ----------------------------------------------------------------------------
 * A GLOBAL FINISHING LAYER, injected once by App\Core\AppShell after the
 * masthead so it is the last stylesheet in <head> on every document. It changes
 * no template, no flow and no existing rule: every style rule here is wrapped in
 * :where(), so it carries ZERO specificity. A page or the design system that
 * already sets a property wins; only a bare, un-styled default is elevated.
 * That zero-specificity contract is the whole safety guarantee, and it is
 * mutation-tested in qa/regression.py.
 *
 * WHY A SEPARATE FILE, INJECTED, NOT THIRTY <head> EDITS. AppShell already
 * injects page-masthead.css and enterprise-navigation.css into every document
 * for exactly this reason. One more link in that same seam lifts all 50 views
 * at once, with no template touched and no flow changed.
 *
 * TWO BANDS:
 *   PART 1  FOUNDATION — depth, focus, motion, print, chrome across every shared
 *           component (cards, buttons, inputs, tables, badges, alerts).
 *   PART 2  STAGE A — the high-value pages (dashboard, reports, billing,
 *           audit-report) get their recurring patterns lifted: KPI metrics,
 *           data-dense tables, page-head hierarchy, definition lists. Still
 *           every rule :where(), still no template edit.
 * ============================================================================ */

/* Decorative-only tokens, namespaced --pe-* so they can never collide with the
   --ds-* system that is under test. */
:root {
  --pe-elevate-1: 0 1px 2px oklch(25% .05 155 / .06), 0 4px 10px -6px oklch(25% .05 155 / .14);
  --pe-elevate-2: 0 1px 2px oklch(25% .05 155 / .06), 0 10px 24px -12px oklch(25% .05 155 / .20);
  --pe-elevate-3: 0 2px 4px oklch(25% .05 155 / .07), 0 22px 46px -20px oklch(25% .05 155 / .28);
  --pe-ring: 0 0 0 3px oklch(83% .145 116 / .55), 0 0 0 5px oklch(37% .105 155 / .35);
  --pe-ease: var(--ds-ease, cubic-bezier(.16, 1, .3, 1));
  --pe-dur: var(--ds-duration, 160ms);
  --pe-hair: oklch(87% .015 126);
}

/* =================================================================== PART 1 */

/* 1. ELEVATION & DEPTH. .ds-card ships flat (border + surface only); give it
   quiet layered depth. Anything that already declares a shadow outranks this. */
:where(.ds-card, .form-panel, .panel:not([class*="alert"]), .report-card, .tool-card) {
  box-shadow: var(--pe-elevate-1);
  transition:
    box-shadow var(--pe-dur) var(--pe-ease),
    transform var(--pe-dur) var(--pe-ease),
    border-color var(--pe-dur) var(--pe-ease);
}
:where(a.ds-card:hover, .ds-card--interactive:hover, .tool-card:hover) {
  box-shadow: var(--pe-elevate-2);
  transform: translateY(-2px);
}
:where(.ds-card--raised) { box-shadow: var(--pe-elevate-3); }
:where(.ds-modal, .ds-dialog, [role="dialog"] > .ds-card, .ds-flyout, .ds-menu) {
  box-shadow: var(--pe-elevate-3);
}

/* 2. FOCUS, MADE VISIBLE ONCE, in the brand's colours, on every interactive
   element - :focus-visible only, so a mouse click never paints the ring. */
:where(a, button, [role="button"], .ds-btn, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--pe-ring);
  border-radius: var(--ds-radius-sm, 8px);
}
:where(.ds-input, .ds-select, .ds-textarea, input, select, textarea):focus-visible {
  outline: none;
  box-shadow: var(--pe-ring);
}

/* 3. BUTTONS WITH BODY. Primary keeps its shape and colour; a hairline top sheen
   and a real shadow give it the weight of the action it carries. */
:where(.ds-btn--primary) {
  background-image: linear-gradient(180deg, oklch(100% 0 0 / .12), oklch(100% 0 0 / 0) 42%);
  box-shadow: var(--pe-elevate-1);
}
:where(.ds-btn--primary:hover) { box-shadow: var(--pe-elevate-2); transform: translateY(-1px); }
:where(.ds-btn--primary:active) { transform: translateY(0); }
:where(.ds-btn--secondary, .ds-btn--ghost) {
  transition: box-shadow var(--pe-dur) var(--pe-ease), transform var(--pe-dur) var(--pe-ease), background-color var(--pe-dur) var(--pe-ease);
}
:where(.ds-btn--secondary:hover) { box-shadow: var(--pe-elevate-1); }

/* 4. INPUTS. The system focuses well; only warm the hover so a form feels alive. */
:where(.ds-input:hover, .ds-select:hover, .ds-textarea:hover) { box-shadow: var(--pe-elevate-1); }

/* 5. TABLES THAT READ. A whisper of zebra and a header that holds its line. */
:where(.ds-table tbody tr:nth-child(even) td) { background: oklch(97.5% .008 118 / .6); }
:where(.ds-table thead th) {
  background: linear-gradient(180deg, oklch(96.5% .012 118), oklch(93.5% .016 116));
  box-shadow: inset 0 -1px 0 var(--ds-border-strong, #7d8375);
}
:where(.ds-table-wrap) { box-shadow: var(--pe-elevate-1); border-radius: var(--ds-radius-lg, 16px); }

/* 6. STATUS, LIFTED off the paper rather than printed into it. */
:where(.ds-badge) { box-shadow: inset 0 1px 0 oklch(100% 0 0 / .5); }
:where(.ds-alert, .alert) { box-shadow: 0 1px 0 oklch(100% 0 0 / .6), var(--pe-elevate-1); }

/* 7. BROWSER CHROME, considered to the edges. */
::selection { background: oklch(83% .145 116 / .40); color: oklch(21.5% .030 151); }
:where(html) { scrollbar-color: var(--ds-border-strong, #7d8375) transparent; }
:where(*)::-webkit-scrollbar { width: 12px; height: 12px; }
:where(*)::-webkit-scrollbar-thumb {
  background: var(--ds-border-strong, #7d8375);
  border: 3px solid transparent; border-radius: 999px; background-clip: content-box;
}
:where(*)::-webkit-scrollbar-thumb:hover { background: var(--ds-text-muted, #536054); background-clip: content-box; }
:where(*)::-webkit-scrollbar-track { background: transparent; }

/* =================================================================== PART 2
   STAGE A — the high-value pages. Their recurring patterns, lifted globally.
   Still :where(), still zero specificity, still no template edit. */

/* A1. KPI METRICS (dashboard, billing, reports). .ds-metric ships flat; give the
   figure the presence a headline number deserves and the card a quiet depth, and
   let a metric that is itself a link lift on hover like any actionable surface. */
:where(.ds-metric) {
  box-shadow: var(--pe-elevate-1);
  transition: box-shadow var(--pe-dur) var(--pe-ease), transform var(--pe-dur) var(--pe-ease);
}
:where(a.ds-metric:hover, .ds-metric--interactive:hover) { box-shadow: var(--pe-elevate-2); transform: translateY(-2px); }
:where(.ds-metric__value) { letter-spacing: -.015em; font-variant-numeric: tabular-nums; }
/* The accent metric's pine rule becomes a soft lime-to-pine wash on its rail edge,
   so the "this is the number that matters" cue reads before the label does. */
:where(.ds-metric--accent) {
  background-image: linear-gradient(90deg, oklch(83% .145 116 / .10), transparent 40%);
}

/* A2. DATA-DENSE TABLES. On the audit and report pages a numeric column should sit
   on tabular figures and align right without a template edit, and the header should
   stay legible when the table scrolls inside its wrapper. */
:where(.ds-table td[data-numeric], .ds-table th[data-numeric]) {
  font-variant-numeric: tabular-nums;
  text-align: right;
}
:where(.ds-table-wrap) { overflow: auto; }
/* ==========================================================================
   v1.80.17. THE ONE DECLARATION THAT MAKES THE STICKY HEADER BELOW REAL.

   THE HEADER HAS NEVER STUCK, ON ANY PAGE, SINCE THE RULE WAS WRITTEN. `position:
   sticky` resolves against the nearest SCROLLING ancestor, which is this wrapper -
   `overflow: auto` makes it one. But nothing ever constrained its height, so the
   wrapper is always exactly as tall as its table, the table never overflows it
   vertically, and an element that cannot scroll has nothing to stick to. The page
   scrolled instead and carried the wrapper, header and all, off the top.

   THREE RELEASES BUILT ON TOP OF THAT. Stage C gives the header a drop shadow "once
   content scrolls beneath it", Stage E gives it a forced-colors border because it
   "loses its shadow", and two print blocks release both. All correct, all inert, and
   five checks in qa/regression.py assert each treatment exists - which is exactly why
   the fix is one declaration here rather than the removal of the feature: deleting the
   header would unpick Stage A, C and E and the print releases with it.

   70vh, NOT A PIXEL HEIGHT. It has to be a fraction of the viewport or a short laptop
   scrolls a table that fits on a desktop. Above it the wrapper scrolls internally and
   the header holds; below it nothing changes at all, which is why most pages here look
   identical - a table has to be taller than 70% of the window before this does anything.

   MAX-HEIGHT, NEVER HEIGHT. `height` would stretch a three-row table into an empty
   panel. This only ever bounds a table that was already too tall.

   RELEASED IN PRINT, and that release is the part that would have caused real damage if
   it were forgotten: a bounded overflow container on paper prints only its first
   screenful and silently truncates the rest of the table. See the print block below.
   ========================================================================== */
:where(.ds-table-wrap) { max-height: 70vh; }
:where(.ds-table-wrap .ds-table thead th) { position: sticky; top: 0; z-index: 2; }

/* A3. PAGE-HEAD HIERARCHY. The shared masthead lead is the one sentence that frames
   a page; give it a touch more air and a measured line length so it reads as a
   deck, not a caption. The eyebrow gets the firm label tracking used elsewhere. */
:where(.ds-page-lead) { max-width: 68ch; line-height: 1.55; }
:where(.ds-page-head .ds-eyebrow) { letter-spacing: var(--ds-tracking-label, .08em); }

/* A4. DEFINITION LISTS (billing terms, report metadata, spec rows). A dt/dd pair
   reads faster with the term in the muted label voice and a hairline between rows,
   which these lists mostly lack. Scoped to the design-system's own dl containers. */
:where(.ds-spec .ds-spec__row + .ds-spec__row, .ds-deflist > div + div) {
  border-top: 1px solid var(--pe-hair);
}

/* A5. SECTION RHYTHM. A run of stacked cards reads as a document when consecutive
   sections are spaced on the system's scale; only applied where nothing set it. */
:where(.ds-card + .ds-card, .ds-section + .ds-section) { margin-top: var(--ds-space-6, 24px); }
/* ==========================================================================================
   v1.79.0. THE RULE ABOVE IS RIGHT FOR A COLUMN AND WRONG INSIDE A GRID, SO IT CANCELS ITSELF.

   Consecutive panels down a page need air, which is what the line above buys. But the moment those
   cards are laid out by a grid or a flex row, `gap` is already doing that job - and the second and
   every later card took 24px ON TOP of the gap, which pushed it out of its own row. Measured in a
   browser at 1280px: three cards that should share one baseline, spread 24px apart.

   FOUR SHIPPED PAGES WERE ON THE WRONG SIDE OF IT - robots-policy, sitemap-quality, webmaster-tools
   and migration-handoff - and ai-providers.css has carried this exact cancel for its own page-local
   `.aip-grid` since v1.22.47. So the fix existed, scoped to one page, for a general defect.

   IT LIVES HERE RATHER THAN IN THE DESIGN SYSTEM, and that is a decision about blast radius as much
   as about meaning. 62 templates link ampuh-design-system.css, so correcting it there costs 62 cache
   busts - the fan-out that made the v1.22.42 manifest wrong. This file is injected by
   AppShell::transform() from ONE versioned place, on every page that carries the shell.
   AND IT IS THE MORE HONEST HOME: a layer that introduces a margin globally is the layer that owes
   the exception, and a reader of the rule above finds its own limit two lines later rather than in
   another file.

   :where() KEEPS THE LAYER'S CONTRACT INTACT, which is the part worth checking rather than assuming.
   Every style rule in this file is zero-specificity so it can never outrank a page, and the suite
   asserts that. This cancel therefore does not win on weight - it wins on ORDER, being the later of
   two zero-specificity rules in the same file. A page that genuinely wants a stacked margin on a grid
   child can still say so with any real selector, exactly as before.
   ========================================================================================== */
:where(.ds-grid > .ds-card, .ds-row > .ds-card) { margin-top: 0; }

/* =================================================================== PART 3
   STAGE B — NAVIGATION & WAYFINDING. The enterprise header/nav is fully owned by
   enterprise-navigation.css with !important on every rule, so this layer neither
   can nor should touch it - that is correct ownership. Stage B instead lifts the
   wayfinding surfaces that are genuinely un-styled: the design-system breadcrumb
   (used on 39 pages, plain today), deep-link :target landing, in-page section
   anchors, and the skip link. Still :where(), still zero specificity. */

/* B1. BREADCRUMB, THE PRIMARY "WHERE AM I". The trail reads faster with a real
   chevron separator instead of a bare slash, a firmer current-page token, and a
   home crumb that looks like the way back. The design-system rules win on
   specificity for anything they set; this only fills what they leave plain. */
:where(.ds-breadcrumb li + li)::before {
  content: "";
  width: 6px; height: 6px;
  border-right: 1.5px solid var(--ds-border-strong, #7d8375);
  border-top: 1.5px solid var(--ds-border-strong, #7d8375);
  transform: rotate(45deg);
  opacity: .7;
}
:where(.ds-breadcrumb a) {
  padding: 2px 6px;
  border-radius: var(--ds-radius-sm, 8px);
  transition: background-color var(--pe-dur) var(--pe-ease), color var(--pe-dur) var(--pe-ease);
}
:where(.ds-breadcrumb a:hover) { background: var(--ds-pine-tint, #eef4f0); text-decoration: none; }
:where(.ds-breadcrumb [aria-current="page"]) {
  padding: 2px 8px;
  border-radius: var(--ds-radius-sm, 8px);
  background: var(--ds-surface-sunken, #e9ebdf);
}
/* The first crumb is home; give it a small house glyph so the exit is obvious. */
:where(.ds-breadcrumb li:first-child a)::before {
  content: "\2302";
  margin-right: 5px;
  opacity: .75;
  font-size: 1.05em;
}

/* B2. DEEP-LINK LANDING. Every route that carries a #fragment (the audit report's
   #assisted-interpretation, settings #gemini, and dozens more) drops the reader at
   an anchor with no confirmation they arrived. A brief, quiet highlight of the
   targeted region answers "here" without a script - and it fades, so it is a cue,
   not a permanent mark. */
:where(:target) {
  scroll-margin-top: var(--ds-space-10, 40px);
}
:where(section:target, article:target, .ds-card:target, li:target, tr:target, [id]:target) {
  animation: pe-target-glow 1.8s var(--pe-ease) 1;
  border-radius: var(--ds-radius-md, 12px);
}
@keyframes pe-target-glow {
  0%   { box-shadow: 0 0 0 3px oklch(83% .145 116 / .0), inset 0 0 0 9999px oklch(83% .145 116 / .0); }
  18%  { box-shadow: 0 0 0 3px oklch(83% .145 116 / .55), inset 0 0 0 9999px oklch(83% .145 116 / .10); }
  100% { box-shadow: 0 0 0 3px oklch(83% .145 116 / .0), inset 0 0 0 9999px oklch(83% .145 116 / .0); }
}

/* B3. IN-PAGE SECTION HEADINGS AS ANCHORS. A heading that owns an id is a landmark
   a colleague can link to; on hover it reveals a link glyph so the reader learns it
   is addressable. Keyboard focus reveals it too, so it is not mouse-only. */
:where(h2[id], h3[id]) { position: relative; scroll-margin-top: var(--ds-space-10, 40px); }
:where(h2[id] > a[href^="#"], h3[id] > a[href^="#"]) {
  opacity: 0;
  margin-left: .4em;
  color: var(--ds-pine, #0e5631);
  text-decoration: none;
  transition: opacity var(--pe-dur) var(--pe-ease);
}
:where(h2[id]:hover > a[href^="#"], h3[id]:hover > a[href^="#"],
       h2[id]:focus-within > a[href^="#"], h3[id]:focus-within > a[href^="#"]) { opacity: .8; }

/* B4. THE SKIP LINK is the first wayfinding control a keyboard or screen-reader user
   meets. The token file positions it; give the focused state the branded ring and a
   little depth so it reads as a real, reachable control when it appears. */
:where(.ds-skip-link:focus-visible) {
  box-shadow: var(--pe-ring), var(--pe-elevate-2);
}

/* =================================================================== PART 4
   STAGE C — DATA-DENSE, GOING FURTHER. The design system already sticks the
   header, zebras the rows (Stage A) and stacks on mobile. Stage C adds the
   density affordances that make a long audit or log table genuinely easy to
   read: a shadow under the sticky header once content scrolls beneath it, a
   right-edge fade cue when a wide table overflows, a highlight on the numeric
   cell the pointer is on, and an opt-in compact density for genuinely dense
   tables. Still :where(), still zero specificity, still no template edit.

   A NOTE ON WHAT IS NOT HERE. A frozen first column was prototyped and dropped:
   the two-axis sticky header cell needs per-table column-width coordination that
   a global, template-free layer cannot guarantee, and a half-working freeze is
   worse than none. It belongs to a dedicated per-page effort, not this layer. */

/* C1. THE STICKY HEADER GETS A FLOOR. A header that sticks with no shadow reads
   as detached from the rows scrolling under it. A hairline drop shadow re-seats
   it. It is on the header cells the system already made sticky, so it inherits
   their position; print and reduced-motion drop it below. */
:where(.ds-table thead th) {
  box-shadow: inset 0 -1px 0 var(--ds-border-strong, #7d8375), 0 6px 10px -8px oklch(25% .05 155 / .30);
}

/* C2. THE OVERFLOW IS SIGNPOSTED. A wide table that scrolls sideways gives no hint
   there is more to the right. A soft right-edge fade, painted on the scroll
   container, says "keep going" - and because it is a background on the wrap, it
   sits behind the cells and never covers data. */
:where(.ds-table-wrap) {
  background:
    linear-gradient(90deg, transparent calc(100% - 28px), oklch(96.7% .012 96 / .9)) right center / 40px 100% no-repeat local;
}

/* C3. COLUMN TRACKING. On a dense grid the eye loses the column between the header
   and the row it wants. Highlighting the hovered cell's whole reading - the number
   and its row - is a template-free approximation: the row already highlights
   (system), and Stage C firms a numeric cell on hover so the figure the pointer is
   on stands proud of its neighbours. */
:where(.ds-table tbody td[data-numeric]:hover) {
  background: oklch(83% .145 116 / .16);
  font-weight: 650;
}

/* C4. DENSITY, ON REQUEST. The 16px default stays for every table. A table that
   opts in with data-density="compact" tightens to a scan-dense rhythm - the right
   choice for a log or a hundred-row diff, the wrong one as a global default, which
   is exactly why it is opt-in and not a redefinition of the base cell. */
:where(.ds-table[data-density="compact"] th),
:where(.ds-table[data-density="compact"] td) {
  padding: var(--ds-space-2, 8px) var(--ds-space-3, 12px);
}
:where(.ds-table[data-density="compact"]) { font-size: var(--ds-font-size-xs, .75rem); }

/* =================================================================== PART 5
   STAGE D — ONBOARDING & CONVERSION. The first thing a new or Trial account sees
   is an empty state and a "what next" list; the thing that grows the account is a
   clear, inviting upgrade path. Both are shared surfaces and both are plain today.
   Stage D lifts them WITHOUT changing a word of copy, a route, or a template:
   the empty state gets warmth and a real primary action, numbered step lists get
   a consistent branded marker across every fragmented per-page implementation, and
   the upgrade actions read as an invitation rather than a locked door. All :where(). */

/* D1. THE EMPTY STATE IS THE FIRST IMPRESSION. .ds-empty ships as a flat dashed box
   on 23 pages - the literal first thing a new account sees. Warm it: a soft branded
   wash, a lifted edge, and centred breathing room so it reads as "start here", not
   "nothing here". The dashed border (system) still wins; this only fills the surface. */
:where(.ds-empty) {
  background:
    radial-gradient(120% 100% at 50% -10%, var(--ds-pine-tint, #eef4f0), transparent 60%),
    var(--ds-surface, #fefdfa);
  box-shadow: var(--pe-elevate-1);
  align-items: center;
  text-align: center;
}
:where(.ds-empty > p),
:where(.ds-empty__body) { max-width: 52ch; }
/* The action inside an empty state is THE next step, so its primary button gets the
   full lifted treatment and a touch more presence than a button in a busy toolbar. */
:where(.ds-empty .ds-btn--primary) { box-shadow: var(--pe-elevate-2); }
:where(.ds-empty .ds-btn--primary:hover) { box-shadow: var(--pe-elevate-3); transform: translateY(-1px); }

/* D2. NUMBERED STEP MARKERS, ONE VOICE. The onboarding "next steps", the per-tool
   "guide steps" and the audit-tools "workflow steps" each drew their own number chip
   in their own stylesheet - three implementations that drift. Give the shared marker
   classes a single branded token look: a pine chip with a lime numeral, the same cue
   the product uses everywhere else. Where a page already set these, its rule wins. */
:where(.next-steps__step, .workflow-steps__num, .guide-steps > li::before) {
  color: var(--ds-lime, #cbe888);
}
:where(.next-steps__step, .workflow-steps__num) {
  box-shadow: 0 2px 6px -2px oklch(25% .05 155 / .35), inset 0 1px 0 oklch(100% 0 0 / .15);
}

/* D3. THE UPGRADE PATH IS AN INVITATION, NOT A WALL. The locked-tool action and any
   explicit upgrade button should feel warm and clickable - the moment an account
   decides to grow. A soft lime sheen and a hover lift say "this way", never "denied".
   Colour and copy are untouched; only depth and motion are added. */
:where(.at-throw--need, [data-upgrade], .ds-btn--upgrade) {
  background-image: linear-gradient(180deg, oklch(83% .145 116 / .16), transparent 55%);
  box-shadow: var(--pe-elevate-1);
  transition: box-shadow var(--pe-dur) var(--pe-ease), transform var(--pe-dur) var(--pe-ease);
}
:where(.at-throw--need:hover, [data-upgrade]:hover, .ds-btn--upgrade:hover) {
  box-shadow: var(--pe-elevate-2);
  transform: translateY(-1px);
}

/* D4. TRIAL / QUOTA METER, READ AS PROGRESS. A "used N of M" figure in a metric is a
   conversion cue when it reads as a fill approaching a limit. Where a metric carries a
   <progress> or a role=progressbar, give the track the brand's lime fill so "you are
   most of the way through your trial" is legible at a glance. Native, no template edit. */
:where(progress) {
  accent-color: var(--ds-pine, #0e5631);
  height: 8px;
}
:where([role="progressbar"]) {
  background: var(--ds-surface-sunken, #e9ebdf);
  border-radius: 999px;
  overflow: hidden;
}

/* =================================================================== PART 6
   STAGE E — ACCESSIBILITY, TO WCAG AA. The earlier stages added depth, focus
   rings, gradients and translucency - all of which need explicit fallbacks so
   they never HARM accessibility in the environments that matter most: Windows
   High Contrast (forced-colors), an OS "increase contrast" setting, and a
   "reduce transparency" setting. A focus ring drawn only with box-shadow, for
   instance, DISAPPEARS in forced-colors - so a keyboard user in high contrast
   would lose the very affordance the premium layer was proud of. Stage E closes
   that. It is the accessibility completion of this whole layer, still :where(),
   still zero specificity, still no template edit. */

/* E1. FORCED-COLORS (Windows High Contrast). The system replaces every colour with
   its own palette and DROPS box-shadow entirely - so the box-shadow focus rings from
   the earlier stages vanish. Restore a real, visible focus indicator with outline,
   which forced-colors DOES honour, in the system's own Highlight colour. Also give
   the decorative sticky-header shadow and the frozen-column separator a border, since
   their shadows are gone. */
@media (forced-colors: active) {
  :where(a, button, [role="button"], .ds-btn, summary, [tabindex],
         .ds-input, .ds-select, .ds-textarea, input, select, textarea):focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
    box-shadow: none;              /* the shadow ring is invisible here anyway */
  }
  /* The sticky header loses its drop shadow in forced-colors; a bottom border keeps
     the boundary between header and rows legible. */
  :where(.ds-table thead th) { border-bottom: 2px solid CanvasText; }
  /* The deep-link landing glow is a box-shadow animation - invisible here - so mark the
     arrived-at target with a real border instead. */
  :where(section:target, article:target, .ds-card:target, li:target, tr:target, [id]:target) {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }
  /* Badges we lifted with an inset highlight need their own border to stay distinct. */
  :where(.ds-badge) { border: 1px solid CanvasText; }
}

/* E2. prefers-contrast: more. When a user asks their OS for MORE contrast, the subtle
   premium tints are the first thing to weaken legibility. Firm every hairline border to
   the strong border token, darken muted separators, and make the focus ring heavier so
   it clears AA non-text contrast (3:1) with room to spare. */
@media (prefers-contrast: more) {
  :where(.ds-card, .ds-metric, .ds-table-wrap, .ds-empty) {
    border: 1px solid var(--ds-border-strong, #7d8375);
  }
  :where(a, button, [role="button"], .ds-btn, summary, [tabindex],
         .ds-input, .ds-select, .ds-textarea, input, select, textarea):focus-visible {
    outline: 3px solid var(--ds-pine-dark, #123c26);
    outline-offset: 2px;
    box-shadow: 0 0 0 5px oklch(83% .145 116 / .8);
  }
  /* The breadcrumb chevron and the numeric-hover tint are decorative and low-contrast;
     firm the current-crumb pill and the hovered cell so they read at higher contrast. */
  :where(.ds-breadcrumb [aria-current="page"]) { outline: 1px solid var(--ds-border-strong, #7d8375); }
  :where(.ds-table tbody td[data-numeric]:hover) { background: oklch(83% .145 116 / .32); }
  /* Zebra rows can wash out; give them a firmer separation under more-contrast. */
  :where(.ds-table tbody tr:nth-child(even) td) { background: oklch(95% .012 118); }
}

/* E3. prefers-reduced-transparency. Any translucent surface (the token file's glass
   nav, and the semi-opaque washes this layer paints) becomes a solid one, so text over
   it never loses contrast to whatever scrolls behind. The overflow fade and the target
   glow's inset wash are the two translucent effects here; make the empty-state wash and
   the upgrade sheen opaque, and drop the overflow fade entirely. */
@media (prefers-reduced-transparency: reduce) {
  :where(.ds-table-wrap) { background: var(--ds-surface, #fefdfa); }
  :where(.ds-empty) { background: var(--ds-surface, #fefdfa); }
  :where(.at-throw--need, [data-upgrade], .ds-btn--upgrade) { background-image: none; }
  :where(.ds-btn--primary) { background-image: none; }
  ::selection { background: var(--ds-lime, #cbe888); }
}

/* E4. A MINIMUM TARGET SIZE, WCAG 2.5.8 (AA). Small inline controls - a breadcrumb
   crumb, a table row action, an icon button - can fall below the 24x24 CSS-px floor.
   Guarantee it without touching layout: a control shorter than the floor gets enough
   min-height, and inline links in dense chrome get a little vertical padding so the hit
   area clears 24px. Only where the design system did not already set a larger --ds-touch. */
:where(.ds-breadcrumb a, .ds-table__actions a, .ds-table__actions button, .ds-badge a) {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
}

/* =================================================================== SAFETY */

/* PRINT IS INK, NOT LIGHT. Every effect this file adds is decorative and must not
   cost toner or muddy a governance printout. Strip it all on paper. */
@media print {
  :where(.ds-card, .ds-metric, .form-panel, .panel, .report-card, .tool-card,
         .ds-btn--primary, .ds-table-wrap, .ds-badge, .ds-alert, .alert,
         .ds-modal, .ds-dialog, .ds-flyout, .ds-menu) {
    box-shadow: none !important;
    transform: none !important;
  }
  :where(.ds-btn--primary) { background-image: none !important; }
  :where(.ds-metric--accent) { background-image: none !important; }
  :where(.ds-table thead th) { background: none !important; }
  :where(.ds-table tbody tr:nth-child(even) td) { background: none !important; }
  :where(.ds-table-wrap .ds-table thead th) { position: static !important; }
  /* Stage B: no landing glow, no anchor glyphs on paper. */
  :where(section:target, article:target, .ds-card:target, li:target, tr:target, [id]:target) {
    animation: none !important; box-shadow: none !important;
  }
  :where(h2[id] > a[href^="#"], h3[id] > a[href^="#"]) { display: none !important; }
  /* Stage C: no sticky-header shadow and no overflow fade on paper - a printout has no
     scroll, so both are noise on the page. */
  :where(.ds-table thead th) { box-shadow: none !important; }
  :where(.ds-table-wrap) { background: none !important; }
  /* v1.80.17. THE BOUND COMES OFF ON PAPER. A max-height with overflow:auto prints its
     first screenful and truncates the rest of the table, which is data loss in the one
     artefact a customer files. Both are released, because either one alone still clips. */
  :where(.ds-table-wrap) { max-height: none !important; overflow: visible !important; }
  /* Stage D: the onboarding warmth and the upgrade sheen are screen conversion cues,
     not ink. Strip the washes and shadows so a printed page stays clean. */
  :where(.ds-empty) { background: none !important; box-shadow: none !important; }
  :where(.ds-empty .ds-btn--primary) { box-shadow: none !important; }
  :where(.at-throw--need, [data-upgrade], .ds-btn--upgrade) {
    background-image: none !important; box-shadow: none !important;
  }
}

/* MOTION IS OPTIONAL. Anyone who stilled their interface gets a still one. */
@media (prefers-reduced-motion: reduce) {
  :where(.ds-card, .ds-metric, .form-panel, .panel, .report-card, .tool-card,
         .ds-btn--primary, .ds-btn--secondary, .ds-btn--ghost,
         a.ds-card, .ds-card--interactive, a.ds-metric) {
    transition: none !important;
  }
  :where(a.ds-card:hover, .ds-card--interactive:hover, .tool-card:hover,
         a.ds-metric:hover, .ds-metric--interactive:hover, .ds-btn--primary:hover) {
    transform: none !important;
  }
  /* Stage B: the deep-link landing glow is motion too - a reader who stilled the
     interface gets the scroll-margin only, no animation. */
  :where(section:target, article:target, .ds-card:target, li:target, tr:target, [id]:target) {
    animation: none !important;
  }
  :where(.ds-breadcrumb a) { transition: none !important; }
  /* Stage D: the empty-state action and upgrade CTAs must not lift for a stilled interface. */
  :where(.ds-empty .ds-btn--primary, .at-throw--need, [data-upgrade], .ds-btn--upgrade) {
    transition: none !important;
  }
  :where(.ds-empty .ds-btn--primary:hover, .at-throw--need:hover, [data-upgrade]:hover, .ds-btn--upgrade:hover) {
    transform: none !important;
  }
}

/* ==========================================================================
   v1.80.16  LAYOUT CONTAINMENT ON CARDS
   --------------------------------------------------------------------------
   WHAT THIS IS AND WHAT IT IS NOT. `contain: layout style` tells the browser
   that a card's internal layout cannot affect anything outside it, so a change
   inside one card is reflowed alone instead of re-laying-out the page. On the
   long surfaces this application actually has - superadmin.php renders 68
   fields, superadmin-maintenance.php 48 badges, google-cloud.php 41 help
   blocks, webmaster-tools.php 19 cards and 12 panels - that is the difference
   between one card's reflow and the document's.

   IT DOES NOT CLIP, AND THAT IS WHY IT IS THE ONLY CONTAINMENT HERE. Paint
   containment clips to the padding box, and this design system puts
   `outline-offset: 2px` on every focus ring: a control at a card's edge would
   have its ring cut off, which is an accessibility regression bought with a
   paint saving. `content-visibility: auto` implies paint containment even while
   the element is on screen, so it is refused for the same reason.

   THE EXTERNAL UI PACK PROPOSED `content-visibility: auto` ON TABLE BODIES AND
   ON SIX SECTION CLASSES. Neither shipped. The six section names
   (.dashboard-section, .projects-list, .audit-results, .billing-section,
   .data-table-wrap, .report-section) match no markup in this tree. And
   containment does not apply to internal table display types at all, so a rule
   on `tbody` is inert: CSS Containment excludes table-row-group from every
   containment type, which is why the pack's headline paint saving was measuring
   nothing.

   FOUR THINGS WERE CHECKED BEFORE THIS SHIPPED, because layout containment
   makes an element a containing block and a new stacking context:

     1. STICKY TABLE HEADERS SURVIVE. `.ds-table thead th` is sticky, and its
        scroll container is `.ds-table-wrap`, which carries `overflow: auto`
        and sits INSIDE the card. Containment on an ancestor of the scroll
        container changes neither the container nor the offsets.
     2. NO ABSOLUTE DESCENDANT LOSES ITS ANCHOR. Every absolutely positioned
        element inside a card in this tree - the metric wash, the billing step
        rail, the plan flag, the audit throw fill - already has a
        `position: relative` ancestor inside the same card.
     3. NO COUNTER CROSSES A CARD. `counter-reset` is declared on the lists
        themselves (`.as-steps`, `.bl-steps`), so style containment cannot
        renumber anything.
     4. NOTHING OVERFLOWS A CARD ON PURPOSE. No flyout, menu, modal or dialog
        markup exists in this tree; those classes are styled and unrendered.

   ZERO SPECIFICITY, AND LAST IN THIS SHEET ON PURPOSE. A page that needs to
   opt out only has to say `contain: none` in its own stylesheet.
   ========================================================================== */
:where(.ds-card, .form-panel, .panel:not([class*="alert"]), .report-card, .tool-card, .ds-metric) {
  contain: layout style;
}
