@import "tailwindcss";
@import "@nuxt/ui";

@custom-variant xs (@media (min-width: 23.5rem));

@theme {
  --breakpoint-xs: 23.5rem; /* 376px — activates comfortable scale on all 360px+ smartphones (375px, 390px, 412px, 444px, 480px) */
}

/* `static` forces emission of every declared theme var — Tailwind v4
   tree-shakes unused `@theme` vars, and Nuxt UI's `--ui-color-primary-*`
   chain references `--color-brand-*` by name even though no utility touches
   `brand-*` directly (the app uses the `primary` alias). Without it the
   brand scale is dropped from the build and all primary-colored surfaces
   render transparent. */
@theme static {
  --font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;

  /* KeluargaMart brand: deep royal blue #142B80 anchored at 500,
     navy #071F68 at 700, light blue #28459A at 400.
     Nuxt UI `primary` maps to this scale (app.config.ts). */
  --color-brand-50: #F0F5FF;
  --color-brand-100: #DCE7FC;
  --color-brand-200: #C4D4F5;
  --color-brand-300: #9DB8EA;
  --color-brand-400: #28459A;
  --color-brand-500: #142B80;
  --color-brand-600: #102268;
  --color-brand-700: #071F68;
  --color-brand-800: #051952;
  --color-brand-900: #04123D;
  --color-brand-950: #020A28;

  /* Micro font sizes for badges, cart counts, and meta labels. These sit below
     the DESIGN.md `label` step (12px) and replace ~80 arbitrary `text-[9/10/11px]`
     values across the codebase with named utilities. */
  --text-tiny: 0.5625rem;   /* 9px  — compact cart-count badges */
  --text-badge: 0.625rem;   /* 10px — product badges, bottom-nav labels, status dots */
  --text-meta: 0.6875rem;   /* 11px — meta labels, trending tags, descriptions */

  /* Promo / discount accent (DESIGN.md "Coral Promo Accent"). The declared
     coral #FA591D (3.23:1) and crimson #EF144A (4.32:1) both fail white AA at
     the 10–11px pill sizes discount badges use, so the solid step is darkened
     to a crimson-coral that clears 4.5:1 with white. This is the SINGLE promo
     color for every discount pill, flash-sale element, and cart-count badge.
       - promo-600 #D61F3F on white  = 5.09:1 (solid pill, white text)
       - promo-700 #B01834 on promo-50/100 = 6.4:1 (soft badge text) */
  --color-promo-50: #FEF2F4;
  --color-promo-100: #FCE4E9;
  --color-promo-200: #F9CDD6;
  --color-promo-600: #D61F3F;
  --color-promo-700: #B01834;
}

/* Tokopedia radius: 8px (0.5rem) default. Nuxt UI v4 remaps its `.rounded-*`
   utilities to `calc(var(--ui-radius) * N)` (sm=1x, md=1.5x, lg=2x, xl=3x) and
   never reads the `--radius-*` variables, so the family values are re-declared
   below unlayered — author rules outside any cascade layer beat the Tailwind
   `utilities` layer regardless of source order. */
:root {
  --ui-radius: 0.5rem;
}

/* controls: 8px (Nuxt UI default = 12px) */
:root .rounded-md { border-radius: 0.5rem; }
/* cards, modals, empty states: 12px (Nuxt UI default = 16px / 24px) */
:root .rounded-lg { border-radius: 0.75rem; }
:root .rounded-xl { border-radius: 0.75rem; }

/* KeluargaMart blue-tinted light surfaces: soft blue page #F5F8FF,
   white elevated cards #FFFFFF, navy text #14213D, slate text #64748B,
   blue-gray borders #D9E2F0. */
.light {
  --ui-bg: #F5F8FF;
  --ui-bg-muted: #EEF3FA;
  --ui-bg-elevated: #FFFFFF;
  --ui-text: #14213D;
  --ui-text-muted: #64748B;
  --ui-text-dimmed: #94A3B8;
  /* #475569 — AA on the tinted page (#F5F8FF, 7.1:1) and muted (#EEF3FA, 6.8:1)
     surfaces where #64748B (text-muted) drops below 4.5:1. Family ink rule:
     use `text-toned` for muted copy that sits on a tinted/muted background. */
  --ui-text-toned: #475569;
  --ui-border: #D9E2F0;
  --ui-border-muted: #E7EDF7;
  --chart-primary: #142B80;
  --chart-accent: #28459A;
  --chart-fill: rgba(20, 43, 128, 0.12);
  --chart-grid: rgba(100, 116, 139, 0.14);
  --chart-text: #64748B;
  --chart-tooltip: rgba(20, 33, 61, 0.94);
}

/* Light mode only (spec §3): the app never applies a dark class — the theme
   tokens above are the only surface values in the build. */
body {
  @apply bg-default text-default antialiased;
}

/* Mobile Chrome auto-zooms out (and keeps it zoomed) whenever the document
   briefly renders wider than the viewport — unstyled pre-hydration flash or
   a late-loading section. Clipping the root's horizontal overflow kills that
   class of "page suddenly zoomed out / layout broken" reports. `clip` (not
   `hidden`) does not create a scroll container, so the sticky header and
   position:fixed overlays keep working. */
html,
body {
  overflow-x: clip;
  max-width: 100%;
}

/* Shared focus-visible indicator. `:where()` keeps this at zero specificity so
   Nuxt UI components that ship their own `focus-visible:ring-*` win, while the
   ~34 raw <button>/<a>/chip controls that only had a UA outline (carousel
   controls, galon steppers, feed filter chips, trending tags, login rows) get
   a guaranteed 2px brand ring. */
:where(a, button, summary, [role="button"], [role="tab"], [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 2px solid var(--color-brand-500);
  outline-offset: 2px;
  border-radius: var(--ui-radius);
}

/* Safe-area insets for mobile devices (notches, Dynamic Island, home indicators) */
.safe-area-bottom {
  padding-bottom: max(1.5rem, env(safe-area-inset-bottom));
}

/* Trailing clearance for the fixed mobile bottom tab bar
   (layouts/default.vue): the bar is ~2.75rem tall (icons + labels + padding),
   so the last CTA on a page must sit above it. `.safe-area-bottom` cannot do
   this job on <main> — as an unlayered author rule its max(1.5rem, env())
   OVERRIDES any Tailwind `pb-*` utility on the same element (unlayered rules
   beat the `utilities` layer), which is exactly how the intended 80px
   `pb-20` clearance silently collapsed to 24px and CTAs started rendering
   underneath the tab bar. sm+ has no bottom bar. */
.pb-tabbar {
  padding-bottom: calc(5rem + env(safe-area-inset-bottom));
}
@media (min-width: 640px) {
  .pb-tabbar {
    padding-bottom: 1.5rem;
  }
}
.safe-area-top {
  padding-top: max(0.5rem, env(safe-area-inset-top));
}

/* docs/DESIGN-DIRECTION.md section 9: reduced motion posture.
   Collapse layout-shifting animations while keeping state transitions. */
@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;
  }
}

/* Sidebar nav highlight: Nuxt UI's default pill variant paints the active
   pill `before:bg-elevated` (white) and the hover pill `before:bg-elevated/50`
   — invisible on the white sidebar. Repaint the ::before pill per the family
   contract (ERP Sidebar.vue: active = bg-primary-soft/text-primary, hover =
   surface-muted). `.sidebar-nav-link` is added to the UNavigationMenu `link`
   slot in the admin/account layouts; reka NavigationMenu renders `data-active`
   on the anchor. Unlayered so it beats the Tailwind utilities layer. */
:root .sidebar-nav-link[data-active]::before { background-color: var(--color-brand-100); }
:root .sidebar-nav-link[data-active] { color: var(--color-brand-500); }
:root .sidebar-nav-link:not([data-active]):hover::before { background-color: var(--ui-bg-muted); }
:root .sidebar-nav-link[data-active]:hover::before { background-color: var(--color-brand-50); }

/* ─── Horizontal scroll rail — hide the scrollbar track on all platforms.
   Nuxt/Tailwind v4 does not ship a `scrollbar-none` utility by default, so we
   declare it here. Apply `no-scrollbar` to any `overflow-x-auto` rail or
   `overflow-y-auto` list where the bar track would be visible (filter chips,
   promo product rails, modal address/city lists, etc.). */
.no-scrollbar {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* IE 11   */
}
.no-scrollbar::-webkit-scrollbar {
  display: none;                  /* Chrome / Safari / Edge */
}

/* ─── 360px small-phone overrides.
   At exactly 360 × 800 (Galaxy A-series, Pixel 4a) the default `sm` (640px)
   break hasn't fired but several elements designed for "mobile" still feel
   cramped.  We tighten selectively without touching the 480px phablet range
   (which looks fine with the base mobile styles). */
@media (max-width: 380px) {
  /* Quick-action grid: shrink icon label to 10px so "Katalog Grosir" fits
     without wrapping to a third line inside the 25% column. */
  .qa-label {
    font-size: 0.5625rem; /* 9px = text-tiny */
    line-height: 1.2;
  }

  /* Hero banner: reduce excessive top padding on the text block so the CTA
     button is always fully visible without scrolling. */
  .banner-text-block {
    padding-top: 0.75rem !important; /* was max-sm:pt-20 = 5rem */
  }
}
