/* ═══════════════════════════════════════════════════════════════════
   components/cross-cutting.css

   Defensive and performance rules that legitimately span many
   components. Living in one file gives each rule a single source of
   truth and matches the duplicate-lint reality: every selector here
   shows up across many components as a multi-selector list.

   Migrated from legacy/app-legacy.css "MODERNIZATION + PERF" block
   (lines 7672-7793) 2026-05-25 as Phase 3c of the legacy-elimination
   plan. Property values are byte-identical to the legacy source.

   Categories:
     1. Typography defenses — text-wrap balance/pretty
     2. Touch-device hover suppression — @media (hover: none)
     3. View transitions — @view-transition
     4. Long-list rendering optimization — content-visibility
     5. Card containment — contain: layout
     6. Scrollbar gutter
   ═══════════════════════════════════════════════════════════════════ */

@layer components {
  /* ── 1. Typography defenses ─────────────────────────────────────
     Better headline rendering — no orphan word on the last line.
     Browser support: Safari 17.4, Chrome 114, Firefox 121.
     Older browsers ignore the property and render normally. */
  .dash-hero__title,
  .services-hero__title,
  .recovery-hero__title,
  .overview-hero__title,
  .dns-hero__title,
  .page-header h1,
  .dash-hero h1,
  .card-title,
  .services-card__title,
  .overview-card__title,
  h1, h2, h3 {
    text-wrap: balance;
  }

  /* Body paragraphs — pretty prevents single-word last lines without
     rebalancing the whole block. Cheaper than balance for long copy. */
  .dash-hero__subtitle,
  .services-hero__subtitle,
  .recovery-hero__subtitle,
  .dash-section p,
  .card-body p {
    text-wrap: pretty;
  }

  /* ── 2. Touch-device hover suppression ──────────────────────────
     On devices without a precise pointer / no real hover, suppress
     the transform-based "lift" effects on cards. Without this,
     tapping a card leaves it visibly lifted until another element is
     tapped — the classic sticky-hover bug.

     We only neutralise transform; box-shadow / colour shifts are
     fine because they fade naturally. */
  @media (hover: none) {
    .dash-infra-item:hover,
    .dash-link-card .gauge-card:hover,
    .dash-link-card:hover .gauge-card,
    .domain-type-card:hover,
    .landing-portal-card:hover,
    .license-stat-card:hover,
    .log-analyzer__stat-card:hover,
    .overview-card:hover .overview-card__inner,
    .overview-card:hover .overview-card__arrow,
    .overview-link-card:hover .overview-link-card__inner,
    .overview-link-card:hover .overview-link-card__arrow,
    .plan-card:hover,
    .settings-dash-card:hover,
    .settings-dash-card:hover .settings-dash-card-arrow,
    .stat-card:hover,
    .template-card:hover,
    .version-card:hover,
    .services-card:hover .services-card__inner,
    .services-card:hover .services-card__arrow,
    .services-link-card:hover .services-link-card__arrow,
    .review-section .btn-link:hover i,
    .wizard-panel .card-footer .btn:hover i.fa-arrow-left,
    .wizard-panel .card-footer .btn:hover i.fa-arrow-right {
      transform: none;
    }

    /* DNS copy button — keep visible on touch (no hover-to-reveal) */
    .dns-copy-btn {
      opacity: 1;
    }
  }

  /* ── 3. View transitions ────────────────────────────────────────
     Auto view transitions for Turbo Drive 8+ navigations. Pages
     cross-fade smoothly without per-route opt-in. Older browsers
     ignore the @view-transition rule.

     Browser support: Chrome 126, Safari 18 (graceful fallback). */
  /* stylelint-disable-next-line at-rule-no-unknown */

  /* ── 4. Long-list rendering optimization ────────────────────────
     Defer rendering of off-screen rows in long tables and lists.
     `auto` keyword tells the browser to remember last size, so
     scrollbar height stays accurate. The intrinsic-size hint avoids
     layout thrash before content paints.

     Browser support: Chrome 85, Safari 18, Firefox 125. */
  .log-analyzer__table tbody tr,
  .audit-event,
  .app-table tbody tr,
  table.table tbody tr {
    content-visibility: auto;
    contain-intrinsic-size: auto 48px;
  }

  /* ── 5. Card containment ────────────────────────────────────────
     Card-shaped components rarely affect layout outside themselves.
     `contain: layout` restricts reflow scope so content updates
     inside one card (badge, async load, tooltip) don't trigger
     ancestor reflow.

     Browser support: universal. */
  .dash-section,
  .dash-infra-card,
  .dash-infra-item,
  .dash-link-card,
  .services-card,
  .services-link-card,
  .overview-card,
  .overview-link-card,
  .landing-portal-card,
  .license-stat-card,
  .license-free-card,
  .log-analyzer__stat-card,
  .plan-card,
  .template-card,
  .version-card,
  .domain-type-card,
  .gauge-card,
  .profile-card,
  .stat-card {
    contain: layout;
  }

  /* ── 6. Scrollbar gutter ────────────────────────────────────────
     Stable scrollbar gutter prevents page jumps when content height
     changes (e.g. modal opens, table renders). */
  html {
    scrollbar-gutter: stable;
  }

  /* ── 7. Card-entry animation ────────────────────────────────────
     Subtle fade-up entry for primary card components on page load,
     with staggered delays across grid columns so they "cascade in".
     Migrated from legacy/app-legacy.css 2026-05-25. */
  @keyframes card-enter {
    from {
      opacity: 0;
      transform: translateY(12px) scale(0.98);
    }
    to {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
  }

  .stat-card,
  .gauge-card,
  .app-panel {
    animation: card-enter 0.4s var(--ease-out) both;
  }

  .row > [class*="col-"]:nth-child(1) > .stat-card,
  .row > [class*="col-"]:nth-child(1) > .gauge-card {
    animation-delay: 60ms;
  }
  .row > [class*="col-"]:nth-child(2) > .stat-card,
  .row > [class*="col-"]:nth-child(2) > .gauge-card {
    animation-delay: 120ms;
  }
  .row > [class*="col-"]:nth-child(3) > .stat-card,
  .row > [class*="col-"]:nth-child(3) > .gauge-card {
    animation-delay: 180ms;
  }
  .row > [class*="col-"]:nth-child(4) > .stat-card,
  .row > [class*="col-"]:nth-child(4) > .gauge-card {
    animation-delay: 240ms;
  }
}

/* ── 7. prefers-reduced-motion — universal a11y override ────────
   Standard pattern from the MDN a11y guide. The selector `*, *::before,
   *::after` cascades to every element, neutralising any
   `transition` / `animation` from base components without requiring
   each one to opt in.

   The portal context has an equivalent rule in `portal/01-foundation.css`,
   but ADMIN context doesn't load that file. cross-cutting.css IS loaded
   by every scope (admin / client / reseller / devise / landing) — putting
   the rule here closes the admin-only reduced-motion gap.

   Why `0.01ms` not `0`: setting `animation-duration: 0` would cancel the
   animation outright, which can break JS that listens for `animationend`
   events. `0.01ms` lets the event fire immediately, keeping JS hooks
   intact. Same trick Bootstrap, MDN, and the GitHub primer all use. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* The @view-transition at-rule MUST live outside @layer (it's a
   top-level browser-managed feature). Kept here so the entire
   cross-cutting concern is in one file. */
@view-transition {
  navigation: auto;
}
