/* ==========================================================================
   BASE — design tokens, reset, typography
   Shared by every page. Component-specific styles live in components.css.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap');

/* ---- Tokens ------------------------------------------------------------ */
:root{
  /* Brand constant — never changes between themes. Hover/focus only. */
  --accent: #FFBF1D;
  --accent-ink: #14140F;

  /* Light theme (default) */
  --bg: #FFFFFF;
  --bg-raised: #F6F6F4;
  --ink: #14141A;
  --ink-text: #0A0A0A;
  --ink-soft: #5B5B63;
  --ink-mute: #8D8D93;
  --hairline: #ECECEA;
  --hairline-strong: #DEDEDC;
  --card-bg: #FFFFFF;
  --card-shadow: 0 2px 6px rgba(20,20,26,0.05), 0 10px 24px rgba(20,20,26,0.05);
  --card-shadow-hover: 0 6px 14px rgba(20,20,26,0.08), 0 18px 36px rgba(20,20,26,0.09);
  --invert-bg: #14141A;
  --invert-ink: #FFFFFF;
  --badge-bg: rgba(255,255,255,0.92);
  --badge-ink: #0A0A0A;

  /* Type */
  --font-display: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Scale */
  --step--1: clamp(0.8125rem, 0.8rem + 0.08vw, 0.875rem);
  --step-0:  clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --step-1:  clamp(1.15rem, 1.1rem + 0.25vw, 1.3rem);
  --step-2:  clamp(1.4rem, 1.3rem + 0.5vw, 1.75rem);
  --step-3:  clamp(1.85rem, 1.6rem + 1.2vw, 2.5rem);
  --step-4:  clamp(2.4rem, 1.95rem + 2.2vw, 3.6rem);
  --step-5:  clamp(2.9rem, 2.2rem + 3.4vw, 4.6rem);

  /* Layout */
  --content-max: 1240px;
  --gutter: 16px;
  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --ease: cubic-bezier(0.65, 0, 0.35, 1);
  --dur: 220ms;
}

[data-theme="dark"]{
  --bg: #101014;
  --bg-raised: #191921;
  --ink: #F5F5F7;
  --ink-text: #F5F5F7;
  --ink-soft: #B7B7C0;
  --ink-mute: #7E7E88;
  --hairline: #26262F;
  --hairline-strong: #34343E;
  --card-bg: #1A1A22;
  --card-shadow: 0 2px 6px rgba(0,0,0,0.3), 0 10px 24px rgba(0,0,0,0.25);
  --card-shadow-hover: 0 6px 16px rgba(0,0,0,0.35), 0 20px 40px rgba(0,0,0,0.3);
  --invert-bg: #F5F5F7;
  --invert-ink: #14141A;
  --badge-bg: rgba(20,20,26,0.85);
  --badge-ink: #F5F5F7;
}

/* ---- Reset --------------------------------------------------------------- */
*, *::before, *::after{ box-sizing: border-box; }
html{
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Safety net: clips any stray element that overflows horizontally on
     narrow screens (decorative blobs, wide skeleton rows, etc.) instead
     of letting the page gain a horizontal scrollbar. Kept on html rather
     than body so it doesn't interfere with position:sticky elements
     inside the page (article TOC, product sidebar). */
  overflow-x: hidden;
}

/* Mobile Safari/Chrome paint their own default gray/blue "flash" over
   whatever's tapped (links, buttons, cards) unless told not to — a
   browser-chrome effect, not anything this stylesheet was drawing, which
   is why it wasn't visible anywhere in this file before. Removed
   site-wide so a tap gives the same clean visual result as a desktop
   click, letting each element's own :hover/:active state (already
   defined per-component throughout this project) be the only visible
   feedback instead of a mismatched system-gray overlay on top of it.
   This does NOT touch :focus-visible below — that's the separate
   keyboard-navigation outline (WCAG accessibility floor for Tab users)
   and stays fully intact for anyone navigating without a mouse/touch. */
*{
  -webkit-tap-highlight-color: transparent;
}

/* ---- Theme transition ----------------------------------------------------
   Every element consumes the same set of --bg/--ink/--card-bg/etc. tokens,
   which flip instantly the moment [data-theme] changes. Without this, most
   elements snap to their new color while only a couple (see body, below)
   had their own transition — different things changing at different
   moments reads as chaotic. This applies one shared, color-only transition
   to everything, so the whole page crossfades as a single coordinated
   motion instead of a patchwork of snaps and fades. Scoped to color/border/
   shadow/fill/stroke only so it never fights a component's own transition
   on transform, opacity, width, etc. (e.g. .reveal, hover lifts). --------- */
*, *::before, *::after{
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              color var(--dur) var(--ease),
              fill var(--dur) var(--ease),
              stroke var(--dur) var(--ease);
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
body{
  margin: 0;
  background: var(--bg);
  color: var(--ink-text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img{ max-width: 100%; display: block; }
a{ color: inherit; text-decoration: none; }
ul, ol{ margin: 0; padding: 0; list-style: none; }
button{ font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input{ font: inherit; color: inherit; }
h1,h2,h3,p{ margin: 0; }

/* Removes the ~300ms delayed-tap / double-tap-to-zoom ambiguity some
   mobile browsers apply to plain links and buttons, so a tap registers
   immediately instead of waiting to see if a second tap follows. Also
   reduces how long a :hover state (see the many :hover rules throughout
   this project's CSS, all written for real mouse hover on desktop) stays
   visibly "stuck" after a touchscreen tap, since touch interactions
   resolve faster and more predictably with this set. */
a, button, input, [role="button"]{
  touch-action: manipulation;
}

/* ---- Typography helpers -------------------------------------------------- */
.font-display{ font-family: var(--font-display); }

h1, h2, h3, .display{
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.12;
}

.eyebrow{
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.meta{
  font-size: var(--step--1);
  color: var(--ink-mute);
}

.meta-row{
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.meta-item{
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--step--1);
  color: var(--ink-mute);
}
.meta-item svg{ width: 16px; height: 16px; flex-shrink: 0; }

/* Shared empty/error-state message, dropped into a grid/rail/flex
   container's innerHTML by every *-supabase.js data loader (home,
   articles, categories, category, products) when a fetch errors out or
   returns zero rows. Previously had no rule anywhere, so the container —
   a grid or centered rail sized only by its (now-gone) skeleton/tile
   children — collapsed down to just this one plain, unstyled line,
   making the whole section look empty/missing rather than showing a
   readable, properly-spaced message.
   grid-column: 1 / -1 makes it span every column when the parent is a
   CSS grid (.category-rail, .recent-grid, .hero-row, etc.) instead of
   sitting cramped in the first cell; harmless on non-grid parents. */
.articles-empty{
  grid-column: 1 / -1;
  width: 100%;
  padding: 2.5rem 1rem;
  text-align: center;
  font-size: var(--step-0);
  color: var(--ink-mute);
}

/* ---- Layout helpers -------------------------------------------------------- */
.wrap{
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.hairline{
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 0;
}
.visually-hidden{
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---- Focus states (accessibility floor) ------------------------------------ */
a:focus-visible,
button:focus-visible,
input:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---- Scroll reveal --------------------------------------------------------- */
.reveal{
  opacity: 0;
  transform: translateY(14px);
  /* Includes the same color/border/shadow set as the universal *
     transition above — this selector's specificity would otherwise
     replace that rule outright and the card would snap between themes
     instead of crossfading like everything else. */
  transition: opacity 600ms var(--ease), transform 600ms var(--ease),
              background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.reveal.is-visible{
  opacity: 1;
  transform: translateY(0);
}

/* ---- Custom scrollbar (site-wide) ------------------------------------------
   Applies to every scrollable area on the public site by default — the main
   page, article tables that overflow horizontally, dropdowns, anything that
   scrolls — so the whole site has one consistent, on-brand scrollbar instead
   of each browser's default one. Matches the admin editor's own scrollbar
   exactly (thin track, pill-shaped thumb using the hairline/mute tones).
   Uses CSS variables throughout, so it automatically matches both light and
   dark mode with no separate [data-theme="dark"] override needed.
   Firefox (scrollbar-color/scrollbar-width) and WebKit/Chromium/Edge
   (::-webkit-scrollbar-*) need separate properties — there's no single
   standard yet that covers both. */
*{
  scrollbar-color: var(--hairline-strong) transparent;
  scrollbar-width: thin;
}
::-webkit-scrollbar{
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track{
  background: transparent;
}
::-webkit-scrollbar-thumb{
  background-color: var(--hairline-strong);
  border-radius: var(--radius-pill);
  border: 2px solid var(--bg);
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover{
  background-color: var(--ink-mute);
}
::-webkit-scrollbar-corner{
  background: transparent;
}
