/* ==========================================================================
   agustín oberg — design tokens v2
   Light and dark are equal citizens. Primitives first, then semantic roles
   per mode, then base components. Source of truth for values: brand.md.

   Theme switching:
   - no attribute          → follows the OS (prefers-color-scheme)
   - [data-theme="light"]  → forced light on <html>
   - [data-theme="dark"]   → forced dark on <html>
   - .theme-light / .theme-dark on any element → forces that subtree
   ========================================================================== */

:root {
  /* --- primitives: mono ----------------------------------------------- */
  --black: #000000;
  --ink-950: #0a0a0a;
  --ink-900: #111111;
  --ink-800: #1f1f1f;
  --ink-700: #2b2b2b;
  --ink-600: #3d3d3d;
  --ink-500: #5c5c5c;
  --ink-400: #8f8f8f;
  --ink-300: #b8b8b8;
  --ink-200: #d9d9d9;
  --ink-150: #e6e6e6;
  --ink-100: #ededed;
  --ink-50: #f4f4f4;
  --white: #ffffff;

  /* --- type ----------------------------------------------------------- */
  --font-display: "Inter Display", "Inter", -apple-system, "SF Pro Display", system-ui, sans-serif;
  --font-text: "Inter", -apple-system, "SF Pro Text", system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --text-2xs: 11px;
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-lg: 18px;
  --text-xl: 22px;
  --text-2xl: 28px;
  --text-3xl: 40px;
  --text-4xl: 56px;
  --text-num: clamp(64px, 11vw, 128px);

  --tracking-display: -0.03em;
  --tracking-tight: -0.015em;
  --tracking-num: -0.045em;
  --tracking-mono: 0.06em;

  /* --- shape ---------------------------------------------------------- */
  --r-xs: 8px;      /* presentation stages: the device is the only round thing */
  --r-md: 16px;     /* thumbnails, inputs, small cards */
  --r-lg: 24px;     /* cards */
  --r-xl: 32px;     /* sheets, floating panels */
  --r-device: 50px; /* phone mockup frame at ~270px wide */
  --r-pill: 999px;  /* every button, chip, toggle and segmented control */

  /* --- space (4px base) ----------------------------------------------- */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;
  --s-10: 160px;

  /* --- motion --------------------------------------------------------- */
  /* Reanimated: Easing.bezier(...) with the same four numbers. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);        /* default: entering, reacting */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);     /* travelling, morphs, exits */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);  /* small confirmations only */

  --dur-1: 120ms;     /* press, hover, label fades */
  --dur-2: 240ms;     /* chips, toggles, color, blur swaps */
  --dur-exit: 280ms;  /* closing anything */
  --dur-3: 420ms;     /* sheets, cards, toasts, morphs */
  --dur-count: 600ms; /* number roll */
  --dur-4: 800ms;     /* headline reveal, hero entrance */

  --stagger-text: 120ms;
  --stagger-word: 30ms;
  --stagger-list: 50ms;  /* cap at 6 items */
  --stagger-digit: 40ms;
  --press-scale: 0.97;
  --lift: 12px;

  /* --- micro-blur ----------------------------------------------------- */
  --blur-text: 4px;     /* words and lines arriving */
  --blur-swap: 6px;     /* state A → state B crossfade */
  --blur-behind: 10px;  /* content behind an open sheet */
  --blur-glass: 20px;   /* glass surfaces */
  --blur-nav: 24px;     /* sticky bars */
  --glass-saturate: 180%;
  --pblur-h: 72px;      /* progressive blur band height */

  /* --- semantic (fixed in both modes) ---------------------------------- */
  --positive: #34c759;
  --warning: #ff9f0a;
  --critical: #ff453a;

  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* ---------- light (default) ---------- */
:root, .theme-light {
  color-scheme: light;
  --bg: var(--ink-50);
  --surface-1: var(--white);
  --surface-2: #f0f0f0;
  --surface-3: var(--ink-150);
  --sheet-bg: var(--white);
  --stage: #e8e8e8;
  --fg: var(--ink-950);
  --fg-2: #6b6b6b;
  --fg-3: #a1a1a1;
  --line: rgba(0, 0, 0, 0.07);
  --line-strong: rgba(0, 0, 0, 0.12);
  --btn-2: var(--ink-150);
  --btn-2-hover: var(--ink-200);
  --glass: rgba(255, 255, 255, 0.68);
  --glass-strong: rgba(255, 255, 255, 0.86);
  --glass-edge: rgba(255, 255, 255, 0.9);
  --scrim: rgba(0, 0, 0, 0.18);
  --focus: rgba(0, 0, 0, 0.55);
  --elev-1: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px -10px rgba(0, 0, 0, 0.1);
  --elev-2: 0 2px 6px rgba(0, 0, 0, 0.04), 0 28px 56px -18px rgba(0, 0, 0, 0.22);
  --device-shadow: 0 40px 80px -28px rgba(0, 0, 0, 0.35), 0 12px 24px -12px rgba(0, 0, 0, 0.2);
  --grain-opacity: 0.05;

  --atmos-fg: var(--ink-950);
  --atmos-fg-2: rgba(0, 0, 0, 0.55);
  --forest-0: #f4f8f3; --forest-1: #e3efe0; --forest-2: #b9dcb3; --forest-glow: #7cc874;
  --ember-0: #fbf7ef;  --ember-1: #f5e7c8;  --ember-2: #eccb83;  --ember-glow: #e0a730;
  --tide-0: #f2f5fc;   --tide-1: #dfe7fa;   --tide-2: #b3c7f2;   --tide-glow: #5b86e8;
  --rouge-0: #fbf2f5;  --rouge-1: #f7dde6;  --rouge-2: #f0b0c6;  --rouge-glow: #e2557f;
}

/* ---------- dark: OS preference ---------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: var(--black);
    --surface-1: var(--ink-900);
    --surface-2: var(--ink-800);
    --surface-3: var(--ink-700);
    --sheet-bg: var(--ink-800);
    --stage: var(--ink-100);
    --fg: var(--white);
    --fg-2: var(--ink-400);
    --fg-3: var(--ink-500);
    --line: rgba(255, 255, 255, 0.08);
    --line-strong: rgba(255, 255, 255, 0.14);
    --btn-2: var(--ink-800);
    --btn-2-hover: var(--ink-700);
    --glass: rgba(255, 255, 255, 0.12);
    --glass-strong: rgba(255, 255, 255, 0.2);
    --glass-edge: rgba(255, 255, 255, 0.14);
    --scrim: rgba(0, 0, 0, 0.55);
    --focus: rgba(255, 255, 255, 0.6);
    --elev-1: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    --elev-2: 0 28px 56px -18px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    --device-shadow: 0 40px 80px -24px rgba(0, 0, 0, 0.6), 0 12px 24px -12px rgba(0, 0, 0, 0.45);
    --grain-opacity: 0.12;

    --atmos-fg: var(--white);
    --atmos-fg-2: rgba(255, 255, 255, 0.65);
    --forest-0: #07130b; --forest-1: #183021; --forest-2: #3f7a45; --forest-glow: #8fd68a;
    --ember-0: #0f0a02;  --ember-1: #3d2905;  --ember-2: #b8821a;  --ember-glow: #ffcf5c;
    --tide-0: #03081a;   --tide-1: #0f2152;   --tide-2: #2f5bd6;   --tide-glow: #8fb4ff;
    --rouge-0: #14030a;  --rouge-1: #4a0d24;  --rouge-2: #d6245e;  --rouge-glow: #ff8fb4;
  }
}

/* ---------- dark: forced (same values) ---------- */
:root[data-theme="dark"], .theme-dark {
  color-scheme: dark;
  --bg: var(--black);
  --surface-1: var(--ink-900);
  --surface-2: var(--ink-800);
  --surface-3: var(--ink-700);
  --sheet-bg: var(--ink-800);
  --stage: var(--ink-100);
  --fg: var(--white);
  --fg-2: var(--ink-400);
  --fg-3: var(--ink-500);
  --line: rgba(255, 255, 255, 0.08);
  --line-strong: rgba(255, 255, 255, 0.14);
  --btn-2: var(--ink-800);
  --btn-2-hover: var(--ink-700);
  --glass: rgba(255, 255, 255, 0.12);
  --glass-strong: rgba(255, 255, 255, 0.2);
  --glass-edge: rgba(255, 255, 255, 0.14);
  --scrim: rgba(0, 0, 0, 0.55);
  --focus: rgba(255, 255, 255, 0.6);
  --elev-1: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --elev-2: 0 28px 56px -18px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  --device-shadow: 0 40px 80px -24px rgba(0, 0, 0, 0.6), 0 12px 24px -12px rgba(0, 0, 0, 0.45);
  --grain-opacity: 0.12;

  --atmos-fg: var(--white);
  --atmos-fg-2: rgba(255, 255, 255, 0.65);
  --forest-0: #07130b; --forest-1: #183021; --forest-2: #3f7a45; --forest-glow: #8fd68a;
  --ember-0: #0f0a02;  --ember-1: #3d2905;  --ember-2: #b8821a;  --ember-glow: #ffcf5c;
  --tide-0: #03081a;   --tide-1: #0f2152;   --tide-2: #2f5bd6;   --tide-glow: #8fb4ff;
  --rouge-0: #14030a;  --rouge-1: #4a0d24;  --rouge-2: #d6245e;  --rouge-glow: #ff8fb4;
}

/* ==========================================================================
   Base components
   ========================================================================== */

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

/* Two-tone headline: statement in fg, supporting line in fg-2. */
.headline {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: 1.3;
  text-wrap: balance;
  color: var(--fg);
}
.headline > span { display: block; }
.headline .muted { color: var(--fg-2); }

/* Mono label: uppercase, tracked, quiet. */
.label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 400;
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--fg-2);
}

/* Big numerals: time, money, scores. */
.num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-num);
  line-height: 0.95;
  letter-spacing: var(--tracking-num);
  font-variant-numeric: tabular-nums;
}

/* Buttons: always pills. Primary is the inverted mode color. */
.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 40px;
  padding: 0 var(--s-4);
  border: 0;
  border-radius: var(--r-pill);
  font-family: var(--font-text);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    transform var(--dur-2) var(--ease-spring),
    background-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out);
}
.btn:active { transform: scale(var(--press-scale)); transition-duration: var(--dur-1); transition-timing-function: var(--ease-out); }
.btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.btn--primary { background: var(--fg); color: var(--bg); }
.btn--primary:hover { background: color-mix(in srgb, var(--fg) 86%, var(--bg)); }
.btn--secondary { background: var(--btn-2); color: var(--fg); }
.btn--secondary:hover { background: var(--btn-2-hover); }
.btn--glass { background: var(--glass); color: var(--fg); backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate)); -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate)); box-shadow: inset 0 1px 0 var(--glass-edge); }
.btn--glass:hover { background: var(--glass-strong); }
.btn--lg { min-height: 52px; padding: 0 var(--s-5); font-size: var(--text-base); }

/* Chip */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border-radius: var(--r-pill);
  background: var(--btn-2);
  color: var(--fg);
  font-family: var(--font-text);
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--positive); }

/* Glass surface */
.glass {
  background: var(--glass);
  backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--line);
}

/* Sheet */
.sheet {
  background: var(--sheet-bg);
  border-radius: var(--r-xl);
  padding: var(--s-5);
  box-shadow: var(--elev-2);
}
.sheet__grabber { width: 36px; height: 5px; margin: 0 auto var(--s-4); border-radius: var(--r-pill); background: var(--line-strong); }

/* Stage: panel that presents a device */
.stage { background: var(--stage); border-radius: var(--r-xs); display: grid; place-items: center; }

/* Atmosphere: radial glow + grain. One per project. Adapts to the mode. */
.atmos {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--atmos-fg);
  background:
    radial-gradient(60% 55% at 50% 38%, color-mix(in srgb, var(--a-glow) 38%, transparent) 0%, transparent 70%),
    radial-gradient(120% 90% at 50% 0%, var(--a-2) 0%, var(--a-1) 45%, var(--a-0) 100%);
}
.atmos::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--grain);
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  pointer-events: none;
}
.atmos--forest { --a-0: var(--forest-0); --a-1: var(--forest-1); --a-2: var(--forest-2); --a-glow: var(--forest-glow); }
.atmos--ember  { --a-0: var(--ember-0);  --a-1: var(--ember-1);  --a-2: var(--ember-2);  --a-glow: var(--ember-glow); }
.atmos--tide   { --a-0: var(--tide-0);   --a-1: var(--tide-1);   --a-2: var(--tide-2);   --a-glow: var(--tide-glow); }
.atmos--rouge  { --a-0: var(--rouge-0);  --a-1: var(--rouge-1);  --a-2: var(--rouge-2);  --a-glow: var(--rouge-glow); }

/* Product accent: the glow of the product's one atmosphere, in both modes.
   Put the class on a container. Use it on one kind of element per screen. */
.accent-forest { --accent: var(--forest-glow); }
.accent-ember  { --accent: var(--ember-glow); }
.accent-tide   { --accent: var(--tide-glow); }
.accent-rouge  { --accent: var(--rouge-glow); }
.btn--accent { background: var(--accent, var(--fg)); color: var(--ink-950); }
.btn--accent:hover { background: color-mix(in srgb, var(--accent, var(--fg)) 88%, var(--ink-950)); }

/* ==========================================================================
   Micro-blur
   ========================================================================== */

/* Progressive blur: four stacked layers, each blurrier and narrower.
   Place inside a positioned scroll container. --dir: to bottom (top edge) / to top (bottom edge). */
.pblur { position: absolute; left: 0; right: 0; height: var(--pblur-h); pointer-events: none; z-index: 2; }
.pblur--top { top: 0; --dir: to bottom; }
.pblur--bottom { bottom: 0; --dir: to top; }
.pblur > i { position: absolute; inset: 0; }
.pblur > i:nth-child(1) { backdrop-filter: blur(1px); -webkit-backdrop-filter: blur(1px); mask-image: linear-gradient(var(--dir), #000 0%, transparent 100%); -webkit-mask-image: linear-gradient(var(--dir), #000 0%, transparent 100%); }
.pblur > i:nth-child(2) { backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); mask-image: linear-gradient(var(--dir), #000 0%, transparent 75%); -webkit-mask-image: linear-gradient(var(--dir), #000 0%, transparent 75%); }
.pblur > i:nth-child(3) { backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); mask-image: linear-gradient(var(--dir), #000 0%, transparent 50%); -webkit-mask-image: linear-gradient(var(--dir), #000 0%, transparent 50%); }
.pblur > i:nth-child(4) { backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); mask-image: linear-gradient(var(--dir), #000 0%, transparent 25%); -webkit-mask-image: linear-gradient(var(--dir), #000 0%, transparent 25%); }
.pblur > i:nth-child(5) { background: linear-gradient(var(--dir), color-mix(in srgb, var(--pblur-tint, var(--bg)) 85%, transparent), transparent); }

/* Blur swap: stacked states; only [data-on] is sharp. */
.swap { display: inline-grid; }
.swap > * {
  grid-area: 1 / 1;
  opacity: 0;
  filter: blur(var(--blur-swap));
  transform: scale(0.96);
  transition: opacity var(--dur-2) var(--ease-out), filter var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.swap > [data-on] { opacity: 1; filter: blur(0); transform: none; }

/* Shimmer: loading or "thinking" text. The only allowed infinite loop in UI. */
.shimmer {
  background: linear-gradient(90deg, var(--fg-3) 0%, var(--fg-3) 35%, var(--fg) 50%, var(--fg-3) 65%, var(--fg-3) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer 2.2s linear infinite;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* Headline reveal: lines go from muted + soft to sharp. Never from invisible. */
.reveal > * { animation: reveal var(--dur-4) var(--ease-out) both; }
.reveal > *:nth-child(2) { animation-delay: var(--stagger-text); }
.reveal > *:nth-child(3) { animation-delay: calc(var(--stagger-text) * 2); }
@keyframes reveal { from { color: var(--fg-3); transform: translateY(6px); filter: blur(var(--blur-text)); } }

/* Word blur-in: JS wraps words in .w and sets --i. Words start faint, never invisible. */
.words .w { display: inline-block; animation: wordIn var(--dur-3) var(--ease-out) both; animation-delay: calc(var(--i, 0) * var(--stagger-word)); }
@keyframes wordIn { from { opacity: 0.15; filter: blur(var(--blur-text)); transform: translateY(4px); } }

/* List stagger: set --i on each child (0..5). */
.stagger > * { animation: rise var(--dur-3) var(--ease-out) both; animation-delay: calc(min(var(--i, 0), 5) * var(--stagger-list)); }
@keyframes rise { from { opacity: 0; transform: translateY(var(--lift)); filter: blur(2px); } }

/* Live dot: pulse ring for live / pending states. */
.live { position: relative; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--positive); }
.live::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: inherit; animation: pulse 1.6s var(--ease-out) infinite; }
@keyframes pulse { from { transform: scale(1); opacity: 0.55; } to { transform: scale(2.6); opacity: 0; } }

/* Floating glass sheet: inset from the screen edge, concentric corners.
   Set --r-outer on the container (screen radius) and --inset (gap to the edge). */
.float-sheet {
  position: absolute;
  left: var(--inset, 12px);
  right: var(--inset, 12px);
  bottom: var(--inset, 12px);
  border-radius: calc(var(--r-outer, 44px) - var(--inset, 12px));
  padding: var(--s-5);
  background: color-mix(in srgb, var(--surface-3) 55%, transparent);
  backdrop-filter: blur(32px) saturate(160%);
  -webkit-backdrop-filter: blur(32px) saturate(160%);
  box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--line), var(--elev-2);
}

/* Edge blur: sharp center, soft edges, like depth of field over a map or photo. */
.edgeblur { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.edgeblur::before {
  content: "";
  position: absolute;
  inset: 0;
  backdrop-filter: blur(10px) saturate(110%);
  -webkit-backdrop-filter: blur(10px) saturate(110%);
  mask-image: radial-gradient(ellipse 70% 62% at 50% 48%, transparent 40%, #000 100%);
  -webkit-mask-image: radial-gradient(ellipse 70% 62% at 50% 48%, transparent 40%, #000 100%);
}

/* Depth text: big word behind the hero object, blurred and quiet. */
.depth-text {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 0.85;
  color: var(--fg);
  opacity: 0.14;
  filter: blur(2.5px);
  user-select: none;
}

/* Contact shadow under a floating object. */
.contact-shadow { width: 70%; height: 14px; margin: -6px auto 0; border-radius: 50%; background: radial-gradient(closest-side, rgba(0, 0, 0, 0.35), transparent); filter: blur(4px); }

/* Link underline grows from the left. */
.link { text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat; transition: background-size var(--dur-2) var(--ease-out); }
.link:hover { background-size: 100% 1px; }

/* ==========================================================================
   Reduced motion: no travel, no scale, no blur. Short crossfades keep state legible.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: var(--dur-1) !important;
    transition-property: opacity, color, background-color !important;
  }
  .shimmer { animation: none !important; color: var(--fg-2); background: none; }
}
