/* ============================================================================
   CAPIFIQ DESIGN TOKENS — single source of truth for SalesOps
   ============================================================================

   WHY THIS FILE EXISTS
   --------------------
   Theme values used to live in three places at once: salesops-dashboard.css
   (dark + light), auth.css (its own dark + light), and four :root blocks in
   design-system.css. They had drifted — the sign-in pages rendered a different
   amber (#ffb32c) from the dashboard (#f5a623) from the product app (#F5A623),
   and the dashboard's light theme used cold GitHub greys against the app's warm
   ones. Adding a CRM surface on top of that would have multiplied the drift.

   This file is now the only place colour, type, space, radius, elevation and
   motion are DEFINED. Everything else consumes var(--…).

   ALIGNMENT WITH THE PRODUCT APP
   ------------------------------
   Layer 1 mirrors Capifiq.App.MVC/wwwroot/css/design-tokens.css value-for-value
   and name-for-name, so the two products are diff-able and a change made there
   can be carried here mechanically. Where a token below has no counterpart in
   the app it is marked NEW — those are the theming and responsive primitives the
   app does not need because it is light-only and fixed-width.

   STRUCTURE — three layers, and the distinction matters
   -----------------------------------------------------
     LAYER 1  PRIMITIVES   Raw scale values. Identical in every theme.
                           Never reference these directly from a component.
     LAYER 2  SEMANTIC     Role-named, theme-dependent. --surface-default,
                           --text-primary, --border-subtle. THIS is what
                           components should use.
     LAYER 3  ALIASES      Legacy names kept pointing at layer 2 so the existing
                           ~3,600 lines of CSS keep working. New work must not
                           add to this layer; it shrinks over time.

   The product app is single-tier: every value is literal in :root, which is
   exactly why it cannot support a dark theme. Layer 2 is the indirection it is
   missing, and is what lets one component rule serve both themes.

   ADDING A TOKEN
   --------------
   Ask which layer it belongs to. A new brand colour is layer 1. "The colour of
   a selected CRM row" is layer 2 and needs a value in BOTH theme blocks. If you
   find yourself writing a hex code outside layer 1, stop.
   ============================================================================ */


/* ============================================================================
   LAYER 1 — PRIMITIVES  (theme-independent; identical light and dark)
   ============================================================================ */

:root {

  /* ── Ink ramp — primary actions ───────────────────────────────────────────
     Primary fills are ink, not amber. Amber is identity (see brand accent). */
  --color-primary-50:  #F4F4F5;
  --color-primary-100: #E4E4E7;
  --color-primary-200: #D4D4D8;
  --color-primary-300: #A1A1AA;
  --color-primary-400: #52525B;
  --color-primary-500: #27272A;
  --color-primary-600: #1A1A1A;   /* primary button fill */
  --color-primary-700: #000000;
  --color-primary-800: #18181B;
  --color-primary-900: #FFFFFF;   /* text on ink fill */

  /* ── Brand accent — Signal Amber ──────────────────────────────────────────
     Active nav, focus rings, brand marks. NOT primary buttons.
     Contrast note: 500 on white is ~1.9:1 and fails for text. Light-theme
     accent TEXT must use 700 (~4.6:1). Layer 2 encodes that so callers cannot
     get it wrong. */
  --brand-accent-50:  #FFFBF0;
  --brand-accent-100: #FEF3C7;
  --brand-accent-200: #FDE68A;
  --brand-accent-400: #FBBC3B;
  --brand-accent-500: #F5A623;   /* the brand spark */
  --brand-accent-600: #D48F1B;
  --brand-accent-700: #B5780F;   /* accessible accent text on light */
  --brand-accent-800: #8A5A09;
  --brand-accent-900: #3D2A05;

  --brand-accent-tint-08:   rgba(245, 166, 35, 0.08);
  --brand-accent-tint-12:   rgba(245, 166, 35, 0.12);
  --brand-accent-tint-30:   rgba(245, 166, 35, 0.30);
  --brand-accent-border-25: rgba(245, 166, 35, 0.25);
  --brand-accent-border-40: rgba(245, 166, 35, 0.40);

  /* ── Ink surfaces — the dark canvas ───────────────────────────────────────
     Shared with the app's dark sidebar so the two feel continuous. SalesOps
     additionally builds its whole dark theme from these. */
  --color-ink-950: #0E1116;
  --color-ink-900: #1A1E25;
  --color-ink-800: #2A2D31;
  --color-ink-700: #3A3E44;
  --color-ink-400: #9C9B98;
  --color-ink-200: #D5D4D1;

  /* ── Neutrals — warm, to pair with amber ──────────────────────────────────
     SalesOps previously used cold GitHub greys (#1f2328 / #636c76) here, which
     is the main reason it read as a different product next to the app. */
  --color-gray-50:  #F9F8F7;
  --color-gray-100: #F2F1EF;
  --color-gray-200: #E5E4E1;
  --color-gray-300: #D1D0CD;
  --color-gray-400: #9C9B98;
  --color-gray-500: #6B6A68;
  --color-gray-600: #4B4A48;
  --color-gray-700: #37362F;
  --color-gray-800: #1F1E1A;
  --color-gray-900: #0F0F0E;

  /* ── Intent ramps — universal; never rebrand these ────────────────────────*/
  --color-success:       #2EA664;
  --color-success-light: #D1FAE5;
  --color-success-dark:  #1F7A48;

  --color-error:         #E24B4A;
  --color-error-light:   #FEE2E2;
  --color-error-dark:    #B83534;
  --color-error-tint-06:   rgba(226, 75, 74, 0.06);
  --color-error-tint-12:   rgba(226, 75, 74, 0.12);
  --color-error-border-25: rgba(226, 75, 74, 0.25);

  --color-warning:       #F59E0B;
  --color-warning-light: #FEF3C7;
  --color-warning-dark:  #C57C07;

  --color-info:          #4A8FE2;
  --color-info-light:    #DBEAFE;
  --color-info-dark:     #2F6FBB;

  --color-danger:        #E24B4A;
  --color-danger-dark:   #B83534;

  /* ── Typography ───────────────────────────────────────────────────────────
     NOTE: neither product ships a webfont. The app names Geist and SalesOps
     named Inter, but no font file or @font-face exists in either, so both fall
     back to the system sans. Geist is named first here to match the app; if a
     webfont is ever added, add it in ONE place — here. */
  --font-sans: 'Geist', 'Inter', ui-sans-serif, system-ui, -apple-system,
               BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
               Arial, sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', ui-monospace,
               SFMono-Regular, Monaco, Consolas, monospace;

  --font-weight-normal:   400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;
  --font-weight-bold:     700;
  --font-weight-extrabold: 800;   /* NEW — SalesOps stat values */

  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.25rem;
  --text-2xl:  1.5rem;
  --text-3xl:  1.875rem;

  --text-display-xl: 4rem;
  --text-display-lg: 2.75rem;
  --text-display-md: 2rem;
  --text-heading-lg: 1.5rem;
  --text-heading-md: 1.125rem;
  --text-body-lg:    1rem;
  --text-body:       0.9375rem;
  --text-body-sm:    0.875rem;
  --text-caption:    0.8125rem;
  --text-caption-sm: 0.75rem;
  --text-micro:      0.6875rem;
  --text-micro-sm:   0.625rem;

  --line-height-tight:   1.25;
  --line-height-normal:  1.5;
  --line-height-relaxed: 1.75;

  --tracking-tight: -0.02em;   /* NEW */
  --tracking-wide:   0.08em;   /* NEW — kickers/eyebrows */

  /* ── Fluid display sizes (NEW) ────────────────────────────────────────────
     Page H1s were clamp()ed inline at each call site with different bounds,
     which is why headings jumped between pages at the same width. */
  --text-fluid-h1: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
  --text-fluid-h2: clamp(1.35rem, 1.1rem + 1vw, 1.875rem);

  /* ── Spacing (4px base) ───────────────────────────────────────────────────*/
  --spacing-0:    0;
  --spacing-px:   1px;
  --spacing-0-5:  0.125rem;
  --spacing-1:    0.25rem;
  --spacing-1-5:  0.375rem;
  --spacing-2:    0.5rem;
  --spacing-2-5:  0.625rem;
  --spacing-3:    0.75rem;
  --spacing-3-5:  0.875rem;
  --spacing-4:    1rem;
  --spacing-5:    1.25rem;
  --spacing-6:    1.5rem;
  --spacing-7:    1.75rem;
  --spacing-8:    2rem;
  --spacing-10:   2.5rem;
  --spacing-12:   3rem;
  --spacing-16:   4rem;

  /* Fluid gutter (NEW) — page padding that shrinks on small screens instead of
     forcing horizontal scroll. */
  --gutter: clamp(1rem, 0.5rem + 2vw, 2rem);

  /* ── Radius ───────────────────────────────────────────────────────────────
     SalesOps used ad-hoc 14/16/20/28px. Aligned to the app's 4px scale;
     --radius-panel keeps the larger card feel where it is deliberate. */
  --border-radius-none: 0;
  --border-radius-sm:   0.25rem;
  --border-radius-md:   0.375rem;
  --border-radius-lg:   0.5rem;
  --border-radius-xl:   0.625rem;
  --border-radius-2xl:  0.75rem;
  --border-radius-full: 9999px;
  --radius-panel:       1rem;      /* NEW — 16px, large surfaces */

  --border-width-0:       0;
  --border-width-default: 1px;
  --border-width-1:       1px;
  --border-width-2:       2px;
  --border-width-4:       4px;

  /* ── Layout (NEW where marked) ────────────────────────────────────────────*/
  --header-height:           56px;
  --sidebar-width:           224px;
  --sidebar-width-collapsed: 56px;

  --modal-max-width-sm: 24rem;
  --modal-max-width-md: 32rem;
  --modal-max-width-lg: 48rem;
  --modal-max-width-xl: 64rem;
  --slide-over-width:   32rem;

  --container-max:     1200px;
  --container-narrow:  880px;
  --container-wide:    1480px;   /* NEW — SalesOps dashboard shells */

  /* ── Breakpoints (NEW) ────────────────────────────────────────────────────
     Media queries cannot read custom properties, so these cannot be consumed
     by @media directly — they are the agreed values, recorded once so the
     hand-written breakpoints stay consistent. SalesOps had 620/980/1100px
     scattered across files with no rationale. Use these:
       sm 640   phone landscape
       md 768   tablet portrait — sidebar collapses below this
       lg 1024  tablet landscape / small laptop
       xl 1280  desktop
       2xl 1536 wide desktop */
  --bp-sm:  640px;
  --bp-md:  768px;
  --bp-lg:  1024px;
  --bp-xl:  1280px;
  --bp-2xl: 1536px;

  /* ── Motion ───────────────────────────────────────────────────────────────*/
  --transition-fast:   150ms cubic-bezier(0.16, 1, 0.3, 1);
  --transition-base:   250ms cubic-bezier(0.16, 1, 0.3, 1);
  --transition-slow:   350ms cubic-bezier(0.16, 1, 0.3, 1);
  --transition-slower: 500ms cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 150ms;
  --duration-base: 250ms;
  --ease-out:      cubic-bezier(0.16, 1, 0.3, 1);

  /* ── Z-index ──────────────────────────────────────────────────────────────*/
  --z-base:                0;
  --z-dropdown:            100;
  --z-sticky:              200;
  --z-fixed:               300;
  --z-modal-backdrop:      400;
  --z-modal:               500;
  --z-slide-over-backdrop: 400;
  --z-slide-over:          500;
  --z-popover:             600;
  --z-tooltip:             700;
  --z-toast:               800;
}


/* ============================================================================
   LAYER 2 — SEMANTIC  (role-named, theme-dependent)

   Components use THESE. Every token here must be defined in both blocks below.
   _ThemeInit always stamps data-theme, so the bare :root copy is only a
   no-JS fallback — it is kept identical to the light block on purpose.
   ============================================================================ */

:root,
:root[data-theme="light"] {
  color-scheme: light;

  /* Surfaces */
  --canvas:            var(--color-gray-50);
  --surface-default:   #FFFFFF;
  --surface-raised:    var(--color-gray-100);
  --surface-sunken:    var(--color-gray-100);
  --surface-overlay:   #FFFFFF;
  --surface-nav:       var(--color-gray-100);
  --surface-input:     #FFFFFF;

  /* Text */
  --text-primary:      var(--color-gray-800);
  --text-secondary:    var(--color-gray-500);
  --text-tertiary:     var(--color-gray-400);
  --text-on-accent:    var(--brand-accent-900);
  --text-on-solid:     var(--color-primary-900);

  /* Borders */
  --border-subtle:     var(--color-gray-200);
  --border-default:    var(--color-gray-300);
  --border-strong:     var(--color-gray-400);

  /* Accent — see the contrast note in layer 1 */
  --accent-solid:      var(--brand-accent-500);
  --accent-hover:      var(--brand-accent-600);
  --accent-text:       var(--brand-accent-700);
  --accent-subtle-bg:  var(--brand-accent-tint-08);
  --accent-border:     var(--brand-accent-border-25);

  /* Intent (theme-tuned foregrounds) */
  --intent-success:      var(--color-success-dark);
  --intent-success-bg:   var(--color-success-light);
  --intent-warning:      var(--color-warning-dark);
  --intent-warning-bg:   var(--color-warning-light);
  --intent-danger:       var(--color-error-dark);
  --intent-danger-bg:    var(--color-error-light);
  --intent-info:         var(--color-info-dark);
  --intent-info-bg:      var(--color-info-light);

  /* Elevation — subtle in light, matching the app's hairline style */
  --elevation-sm: 0 1px 2px rgba(0,0,0,0.04), 0 0 0 0.5px rgba(0,0,0,0.06);
  --elevation-md: 0 2px 8px rgba(0,0,0,0.06), 0 0 0 0.5px rgba(0,0,0,0.06);
  --elevation-lg: 0 4px 16px rgba(0,0,0,0.08), 0 0 0 0.5px rgba(0,0,0,0.06);
  --elevation-xl: 0 8px 32px rgba(0,0,0,0.10), 0 0 0 0.5px rgba(0,0,0,0.06);

  --focus-ring: 0 0 0 2px var(--brand-accent-tint-30);
  --scrim: rgba(15, 15, 14, 0.45);
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --canvas:            var(--color-ink-950);
  --surface-default:   var(--color-ink-900);
  --surface-raised:    var(--color-ink-800);
  --surface-sunken:    #0A0D11;
  --surface-overlay:   var(--color-ink-900);
  --surface-nav:       #0A0D11;
  --surface-input:     var(--color-ink-950);

  --text-primary:      #F5F6F8;
  --text-secondary:    var(--color-ink-400);
  --text-tertiary:     #7A7E85;
  --text-on-accent:    var(--brand-accent-900);
  --text-on-solid:     var(--color-primary-900);

  --border-subtle:     rgba(255, 255, 255, 0.08);
  --border-default:    var(--color-ink-800);
  --border-strong:     var(--color-ink-700);

  /* 500 clears 8:1 on the ink canvas, so dark can use the pure brand colour
     for text as well as fills. */
  --accent-solid:      var(--brand-accent-500);
  --accent-hover:      var(--brand-accent-400);
  --accent-text:       var(--brand-accent-400);
  --accent-subtle-bg:  var(--brand-accent-tint-12);
  --accent-border:     var(--brand-accent-border-25);

  /* Light ramp values are used as the FOREGROUND on dark, and the base colour
     at low alpha as the background — inverting the light-theme relationship. */
  --intent-success:      #6EE7A8;
  --intent-success-bg:   rgba(46, 166, 100, 0.14);
  --intent-warning:      #FCD34D;
  --intent-warning-bg:   rgba(245, 158, 11, 0.14);
  --intent-danger:       #FCA5A5;
  --intent-danger-bg:    rgba(226, 75, 74, 0.16);
  --intent-info:         #93C5FD;
  --intent-info-bg:      rgba(74, 143, 226, 0.16);

  --elevation-sm: 0 1px 2px rgba(0,0,0,0.40), 0 0 0 0.5px rgba(255,255,255,0.06);
  --elevation-md: 0 4px 14px rgba(0,0,0,0.45), 0 0 0 0.5px rgba(255,255,255,0.06);
  --elevation-lg: 0 10px 30px rgba(0,0,0,0.50), 0 0 0 0.5px rgba(255,255,255,0.06);
  --elevation-xl: 0 20px 50px rgba(0,0,0,0.55), 0 0 0 0.5px rgba(255,255,255,0.06);

  --focus-ring: 0 0 0 2px var(--brand-accent-tint-30);
  --scrim: rgba(0, 0, 0, 0.65);
}


/* ============================================================================
   LAYER 3 — COMPATIBILITY ALIASES

   The pre-existing ~3,600 lines of SalesOps CSS reference these names. Pointing
   them at layer 2 re-themes all of it without a risky big-bang rename, and
   makes the two themes derive from one palette instead of two hand-tuned sets.

   var() resolves at use time, so these work on :root even though the theme
   blocks above have higher specificity.

   DO NOT ADD TO THIS LAYER. New rules use layer 2 names.
   ============================================================================ */

:root {
  /* salesops-dashboard.css */
  --salesops-bg:            var(--canvas);
  --salesops-panel:         var(--surface-default);
  --salesops-panel-strong:  var(--surface-raised);
  --salesops-line:          var(--accent-border);
  --salesops-line-soft:     var(--border-subtle);
  --salesops-text:          var(--text-primary);
  --salesops-muted:         var(--text-secondary);
  --salesops-accent:        var(--accent-solid);
  --salesops-accent-strong: var(--accent-text);

  --page-bg:          var(--canvas);
  --surface:          var(--surface-default);
  --sidebar-bg:       var(--surface-nav);
  --input-bg:         var(--surface-input);
  --border:           var(--border-default);
  --border-light:     var(--border-subtle);
  --accent:           var(--accent-solid);
  --success:          var(--intent-success);
  --warning:          var(--intent-warning);
  --danger:           var(--intent-danger);
  --shadow:           var(--elevation-lg);
  --overlay:          var(--scrim);
  --card-bg:          var(--surface-default);
  --card-hover-bg:    var(--accent-subtle-bg);
  --button-text:      var(--text-on-accent);
  --menu-shadow:      var(--elevation-lg);
  --avatar-bg:        var(--surface-raised);
  --accent-soft-bg:     var(--accent-subtle-bg);
  --accent-soft-border: var(--accent-border);

  --theme-toggle-bg:       var(--surface-default);
  --theme-toggle-bg-hover: var(--accent-subtle-bg);
  --brand-mark-bg:         var(--surface-default);
  --brand-mark-border:     var(--accent-border);
  --brand-mark-shadow:     var(--elevation-md);

  /* Was an amber radial gradient. It only covered the areas that did NOT paint their own
     background, so the content column carried a brown cast while the sidebar and header beside it
     stayed neutral — read as a colour mismatch rather than as a deliberate wash. Flattened to the
     canvas, which is also what the product app does. Kept as an alias for existing references. */
  --ambient-bg: var(--canvas);

  /* Transcript + presence */
  --transcript-visitor-bg: var(--accent-subtle-bg);
  --transcript-human-bg:   var(--intent-success-bg);
  --transcript-system-bg:  var(--surface-raised);
  --status-neutral-bg:     var(--surface-raised);
  --status-online-bg:      var(--intent-success-bg);
  --status-online-border:  var(--intent-success);
  --status-online-text:    var(--intent-success);
  --status-idle-bg:        var(--intent-warning-bg);
  --status-idle-border:    var(--intent-warning);
  --status-idle-text:      var(--intent-warning);
  --status-offline-bg:     var(--intent-danger-bg);
  --status-offline-border: var(--intent-danger);
  --status-offline-text:   var(--intent-danger);
  --warning-bg:            var(--intent-warning-bg);
  --warning-border:        var(--intent-warning);
  --warning-text:          var(--intent-warning);

  /* design-system.css */
  --border-light-color: var(--border-subtle);
  --shadow-sm: var(--elevation-sm);
  --shadow-md: var(--elevation-md);
  --shadow-lg: var(--elevation-lg);
  --shadow-xl: var(--elevation-xl);
  --accent-strong: var(--accent-text);

  /* auth.css — was a THIRD palette with its own amber (#ffb32c). */
  --auth-background:     var(--canvas);
  --auth-panel:          var(--surface-default);
  --auth-input:          var(--surface-input);
  --auth-border:         var(--border-default);
  --auth-primary:        var(--accent-solid);
  --auth-primary-hover:  var(--accent-hover);
  --auth-text:           var(--text-primary);
  --auth-muted:          var(--text-secondary);
  --auth-error:          var(--intent-danger);
  --auth-success:        var(--intent-success);

  --text-muted:      var(--text-secondary);
  --surface-hover:   var(--surface-raised);

  --theme-toggle-border: var(--border-default);
  --theme-toggle-shadow: var(--elevation-md);

  /* Remaining auth.css surface detail */
  --auth-line:               var(--border-subtle);
  --auth-line-amber:         var(--accent-border);
  --auth-input-focus:        var(--surface-input);
  --auth-input-hover-border: var(--border-strong);
  --auth-placeholder:        var(--text-tertiary);
  --auth-link-hover:         var(--accent-hover);
  --auth-secondary-hover:    var(--surface-raised);
  --auth-google-bg:          var(--surface-default);
  --auth-google-hover:       var(--surface-raised);
  --auth-success-bg:         var(--intent-success-bg);
  --auth-success-border:     var(--intent-success);
  --auth-danger-bg:          var(--intent-danger-bg);
  --auth-danger-border:      var(--intent-danger);
  --auth-form-shadow:        none;
  --auth-logo-bg:            var(--surface-default);
  --auth-logo-border:        var(--border-subtle);

  /* The auth split-screen visual sits on a photograph, so its text is white in
     BOTH themes. These are deliberately NOT themed. */
  --auth-media-heading:      #FFFFFF;
  --auth-media-text:         rgba(255, 255, 255, 0.90);
  --auth-media-muted:        rgba(255, 255, 255, 0.76);
  --auth-media-badge-bg:     rgba(8, 10, 14, 0.54);
  --auth-media-badge-border: var(--brand-accent-border-40);
  --auth-media-badge-text:   var(--brand-accent-400);
  --auth-visual-overlay: linear-gradient(to bottom,
      rgba(8, 10, 14, 0.06) 0%, rgba(8, 10, 14, 0.24) 42%, rgba(8, 10, 14, 0.78) 100%);

  /* Inbox — these were referenced by salesops-dashboard.css but never defined
     anywhere, so every rule using them silently fell back to nothing. Defining
     them here on the shared scale is the fix. */
  --inbox-space-1: var(--spacing-1);
  --inbox-space-2: var(--spacing-2);
  --inbox-space-3: var(--spacing-3);
  --inbox-space-6: var(--spacing-6);
  --inbox-radius-sm: var(--border-radius-md);
  --inbox-radius:    var(--border-radius-lg);
  --inbox-radius-lg: var(--border-radius-2xl);
  --inbox-motion:    var(--transition-fast);
  --inbox-shadow-selected: var(--focus-ring);

  /* Spacing aliases — design-system.css uses --space-N (px), layer 1 uses
     --spacing-N (rem). Same scale, different unit and name. */
  --space-1: var(--spacing-1);
  --space-2: var(--spacing-2);
  --space-3: var(--spacing-3);
  --space-4: var(--spacing-4);
  --space-5: var(--spacing-5);
  --space-6: var(--spacing-6);
  --space-8: var(--spacing-8);
  --space-10: var(--spacing-10);
  --space-12: var(--spacing-12);
  --space-16: var(--spacing-16);
}


/* ============================================================================
   BASE — the small amount of global styling that belongs with the tokens
   ============================================================================ */

html {
  -webkit-text-size-adjust: 100%;   /* stop iOS inflating text in landscape */
}

body {
  background: var(--canvas);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-body-lg);
  line-height: var(--line-height-normal);
}

/* NO overflow-x guard here, deliberately.

   This briefly carried `html, body { overflow-x: hidden }` as a backstop against sideways scroll
   on phones. It broke vertical scrolling across the whole app: `overflow-x: hidden` forces the
   used value of `overflow-y` to `auto`, so body became a scroll container wrapping the entire
   page at full content height — it could never scroll itself, so it swallowed the wheel and the
   page could only be moved by dragging the scrollbar. Putting it on html compounded that by
   stopping body's overflow propagating to the viewport.

   `overflow-x: clip` avoids the scroll-container problem but, measured, does not actually stop
   the viewport scrolling sideways — so it buys nothing here.

   Horizontal overflow is instead prevented at its source: `min-width: 0` on the grid/flex children
   that would otherwise refuse to shrink (see salesops-dashboard.css) and `overflow-wrap: anywhere`
   on text below. Those are verified at 390/768/1280. A page-level clip would only have hidden a
   regression in those rules rather than surfacing it. */
body { max-width: 100%; }

/* Media and embedded content default to fitting their container. */
img, svg, video, canvas, iframe { max-width: 100%; height: auto; }

/* Long tokens — emails, URLs, IDs — are everywhere in a CRM and are the usual
   cause of a table or card blowing out its column on a narrow screen. */
:where(td, th, p, li, dd, dt, h1, h2, h3, h4) { overflow-wrap: anywhere; }

@media (prefers-reduced-motion: reduce) {
  :root {
    --transition-fast: 0ms; --transition-base: 0ms;
    --transition-slow: 0ms; --transition-slower: 0ms;
    --duration-fast: 0ms;   --duration-base: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
