/* ============================================================================
   public/css/base.css — Resets, typography defaults, document-level styles
   ============================================================================ */

/* Matches the app.html / login.html link tags (FBA stack, 2026-07-27).
   Fraunces dropped: --font-display resolved to Cormorant well before this
   change, so the only things still naming it were the stale 'opsz'/'SOFT'
   font-variation-settings below, which Cormorant ignores either way. */
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Geist+Mono:wght@400;500&display=swap');

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  font-family: var(--font-body);
  font-size: var(--type-body-md);
  font-weight: var(--weight-regular);
  line-height: var(--line-body);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  background: var(--surface-base);
  font-feature-settings: 'ss01', 'cv11';   /* DM Sans stylistic alternates for distinct character shapes */
}

/* ----- Tabular numbers everywhere by default ------------------------------- */
table, .num, .metric, input[type='number'] {
  font-feature-settings: 'tnum', 'lnum';   /* tabular numerals, lining */
}

/* ----- Typography classes -------------------------------------------------- */

.display-xl, .display-lg, .display-md, .display-sm {
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-display);
  line-height: var(--line-display);
  /* Optical sizing — Fraunces adjusts contrast at large sizes */
  font-optical-sizing: auto;
}

.display-xl { font-size: var(--type-display-xl); font-variation-settings: 'opsz' 144, 'SOFT' 50; }
.display-lg { font-size: var(--type-display-lg); font-variation-settings: 'opsz' 96,  'SOFT' 50; }
.display-md { font-size: var(--type-display-md); font-variation-settings: 'opsz' 48; }
.display-sm { font-size: var(--type-display-sm); font-variation-settings: 'opsz' 24; }

.body-lg { font-size: var(--type-body-lg); line-height: var(--line-body); }
.body-md { font-size: var(--type-body-md); line-height: var(--line-body); }
.body-sm { font-size: var(--type-body-sm); line-height: var(--line-body); color: var(--text-secondary); }
.body-xs { font-size: var(--type-body-xs); line-height: var(--line-body); color: var(--text-tertiary); }

.metric-xl, .metric-lg, .metric-md {
  font-family: var(--font-body);
  font-weight: var(--weight-medium);
  font-feature-settings: 'tnum', 'lnum', 'ss01';
  letter-spacing: var(--tracking-tight);
  line-height: var(--line-display);
  color: var(--text-primary);
}
.metric-xl { font-size: var(--type-metric-xl); }
.metric-lg { font-size: var(--type-metric-lg); }
.metric-md { font-size: var(--type-metric-md); }

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--type-body-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-uppercase);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.mono {
  font-family: var(--font-mono);
  font-feature-settings: 'tnum', 'lnum';
}

/* ----- Links --------------------------------------------------------------- */
a {
  color: var(--action-primary);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--duration-fast) var(--ease-out);
}
a:hover {
  border-bottom-color: var(--action-primary);
}

/* ----- Selection ----------------------------------------------------------- */
::selection {
  background: var(--brand-pink-ivory);
  color: var(--text-primary);
}

/* ----- Focus rings — visible but refined ----------------------------------- */
:focus-visible {
  outline: 2px solid var(--action-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ----- Scrollbars — minimal, off-white -------------------------------------- */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-subtle);
  border-radius: var(--radius-pill);
  border: 2px solid var(--surface-base);
}
::-webkit-scrollbar-thumb:hover { background: var(--border-default); }

/* ----- Motion preference --------------------------------------------------- */
@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;
  }
}

/* ============================================================================
   PAGE RHYTHM — canonical macro-whitespace
   ============================================================================
   The ZS Retail app uses a deliberate rhythm between elements:
     - Page header → first section:  --space-10 (40px)
     - Section → next section:        --section-gap (48px)
     - Section header → first child:  --space-5 (20px)
     - Card → adjacent card:          --space-4 (16px)
     - Tile cluster gap:              --space-3 to --space-4

   These tokens live in tokens.css. Pages should:
     1. Wrap their header in <div class="page-header">
     2. Wrap each major content block in <section class="section">
        OR use the .page-section-gap utility for inline spacing
   ============================================================================ */
.section {
  margin-bottom: var(--section-gap);
}
.section:last-child {
  margin-bottom: 0;
}

/* Utility for one-off inline section-style spacing without the .section
   wrapper overhead (used in Replenishment, Campaign Builder, etc. where
   <section> elements already have role-based class names like .ed-bezel) */
.page-section-gap {
  margin-bottom: var(--space-6); /* 24px — slightly tighter than .section's 48px */
}
.page-section-gap-lg {
  margin-bottom: var(--section-gap); /* 48px */
}

/* Hero/tile cluster — consistent gap for the summary-tile pattern */
.tile-cluster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

/* ----------------------------------------------------------------------------
   SKIP LINK — first tab stop on the page.
   Visually hidden until focused, then pinned top-left over the topbar. Uses
   clip-path rather than display:none / visibility:hidden, both of which remove
   the element from the tab order entirely and would defeat the purpose.
   Target is #mainContent, which carries tabindex="-1" so focus actually lands.
---------------------------------------------------------------------------- */
.skip-link {
  position: fixed;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-toast);
  padding: 10px 16px;
  background: var(--ed-emerald);
  color: var(--ed-cream);
  font-family: var(--ed-grotesk);
  font-size: var(--type-body-sm);
  font-weight: var(--weight-medium);
  border: 1px solid var(--ed-emerald-deep);
  border-radius: var(--radius-button);
  box-shadow: var(--shadow-lg);
  text-decoration: none;
  /* Hidden but focusable */
  clip-path: inset(50%);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}
.skip-link:focus,
.skip-link:focus-visible {
  clip-path: none;
  opacity: 1;
  transform: translateY(0);
  border-bottom-color: var(--ed-emerald-deep);   /* beat the global a:hover rule */
}

/* The skip target should not draw a focus ring when reached programmatically —
   it is a scroll destination, not a control. */
#mainContent:focus { outline: none; }
#mainContent:focus-visible { outline: none; }

/* ----------------------------------------------------------------------------
   TOUCH TARGETS
   Gated on `pointer: coarse`, NOT a width breakpoint. A narrow desktop window
   is still a mouse and should keep the dense sizing; a tablet at 1024px is a
   finger and should not. This is the distinction a max-width query gets wrong
   in both directions.

   44px is the WCAG 2.5.5 (AAA) / Apple HIG figure. We hit it with min-height
   plus centring rather than extra padding, so the visual weight of the control
   is unchanged — only its hit area grows.
---------------------------------------------------------------------------- */
@media (pointer: coarse) {
  .btn,
  .btn-sm,
  .ed-btn,
  .scope-btn,
  .sidebar-link,
  .topbar-menu-btn,
  [role='button'] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Sidebar links are full-width block targets, not centred pills. */
  .sidebar-link { justify-content: flex-start; }

  /* Icon-only controls need width as well — a 44px-tall, 20px-wide target
     still misses. Listed explicitly rather than inferred with :has(), which
     would also catch text buttons that happen to carry an aria-label.
     (.btn-icon and .scope-btn are defined in CSS but never used in markup —
     not listed here so this block does not imply they are live.) */
  .topbar-menu-btn,
  .modal-close {
    min-width: 44px;
  }

  /* Rows carry inline actions; without this the 44px minimum collides with
     the density pass's 8px cell padding and the row clips. */
  .data-table td {
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
  }
}

/* Checkboxes and radios are still NOT given min-height/min-width directly:
   those properties stretch the UA-drawn control into a distorted box rather
   than growing its hit area.

   The fix is to grow the LABEL instead. Every checkbox in the app now sits
   inside a <label> (the two bulk-select cells in Inventory were <div> wrappers
   until 2026-07-27), so the label is the hit target and can be sized freely
   while the control keeps its native 13px appearance. */
@media (pointer: coarse) {
  .bulk-checkbox-cell,
  label:has(> input[type='checkbox']),
  label:has(> input[type='radio']) {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
  }
  /* The bulk-select cells hold nothing but the box, so they need width too —
     the labelled ones get theirs from their text. */
  .bulk-checkbox-cell { min-width: 44px; justify-content: center; }
}
