/* ============================================================
   CHRISTOPHER FERNANDEZ — DESIGN SYSTEM EXTENSIONS
   Version 1.0 · May 2026
   
   Requires: cf-design-system.css (load first)
   Usage: <link rel="stylesheet" href="cf-design-system-extensions.css">
   
   Contents:
   1. Animation utilities
   2. Grid framework
   3. Dark mode colour overrides
   ============================================================ */


/* ============================================================
   1. ANIMATION UTILITIES
   ============================================================
   
   Philosophy: animation should feel editorial, not playful.
   Movements are precise, purposeful, and restrained.
   No bouncing, no spinning, no decorative motion.
   
   Usage patterns:
   - Page load: use .cf-fade-up on sections with staggered delay
   - Hover: use .cf-hover-lift on cards and links
   - Reveal: use .cf-reveal with IntersectionObserver (JS snippet below)
   - Transition: use cf-transition-* on interactive elements
   ============================================================ */

/* --- Keyframes --- */

@keyframes cf-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes cf-fade-up {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes cf-fade-down {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes cf-slide-in-left {
  from { opacity: 0; transform: translateX(-24px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes cf-slide-in-right {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes cf-bar-grow {
  from { transform: scaleX(0); transform-origin: left; }
  to   { transform: scaleX(1); transform-origin: left; }
}

@keyframes cf-dot-appear {
  from { opacity: 0; transform: scale(0); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes cf-underline-grow {
  from { width: 0; }
  to   { width: 100%; }
}


/* --- Entrance animations --- */
/* Apply directly or combine with .cf-reveal for scroll-triggered behaviour */

.cf-anim-fade-in {
  animation: cf-fade-in 0.5s ease forwards;
}

.cf-anim-fade-up {
  animation: cf-fade-up 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.cf-anim-fade-down {
  animation: cf-fade-down 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.cf-anim-slide-left {
  animation: cf-slide-in-left 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.cf-anim-slide-right {
  animation: cf-slide-in-right 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* Signature bar grow — for page load and section reveals */
.cf-anim-bar-grow {
  animation: cf-bar-grow 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* Amber dot pop — delayed after bar grow */
.cf-anim-dot-appear {
  animation: cf-dot-appear 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) 0.5s both;
}


/* --- Delay utilities --- */
/* Combine with any cf-anim-* class for staggered reveals */

.cf-delay-0   { animation-delay: 0ms; }
.cf-delay-100 { animation-delay: 100ms; }
.cf-delay-150 { animation-delay: 150ms; }
.cf-delay-200 { animation-delay: 200ms; }
.cf-delay-300 { animation-delay: 300ms; }
.cf-delay-400 { animation-delay: 400ms; }
.cf-delay-500 { animation-delay: 500ms; }
.cf-delay-600 { animation-delay: 600ms; }
.cf-delay-750 { animation-delay: 750ms; }


/* --- Duration utilities --- */

.cf-duration-200 { animation-duration: 200ms; }
.cf-duration-400 { animation-duration: 400ms; }
.cf-duration-600 { animation-duration: 600ms; }
.cf-duration-800 { animation-duration: 800ms; }
.cf-duration-1000 { animation-duration: 1000ms; }


/* --- Easing utilities --- */

.cf-ease-linear  { animation-timing-function: linear; }
.cf-ease-smooth  { animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }
.cf-ease-spring  { animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); }
.cf-ease-out     { animation-timing-function: ease-out; }


/* --- Scroll-reveal system --- */
/*
   Elements start hidden. JS adds .is-visible when they enter the viewport.
   Use with the IntersectionObserver snippet at the bottom of this file.
   
   Example:
   <h1 class="cf-reveal cf-anim-fade-up">Heading</h1>
   <p class="cf-reveal cf-anim-fade-up cf-delay-200">Paragraph</p>
*/

.cf-reveal {
  opacity: 0;
  animation: none;
}

.cf-reveal.is-visible {
  animation-fill-mode: forwards;
  animation-play-state: running;
}

.cf-reveal.cf-anim-fade-up.is-visible    { animation: cf-fade-up    0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards; }
.cf-reveal.cf-anim-fade-in.is-visible    { animation: cf-fade-in    0.5s ease forwards; }
.cf-reveal.cf-anim-slide-left.is-visible { animation: cf-slide-in-left 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards; }
.cf-reveal.cf-anim-slide-right.is-visible { animation: cf-slide-in-right 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards; }


/* --- Hover micro-interactions --- */

/* Card lift — subtle upward shift on hover */
.cf-hover-lift {
  transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1),
              opacity 200ms ease;
}
.cf-hover-lift:hover {
  transform: translateY(-3px);
}

/* Fade on hover — for article card lists */
.cf-hover-fade {
  transition: opacity 150ms ease;
}
.cf-hover-fade:hover {
  opacity: 0.65;
}

/* Amber underline grow — for nav links and CTAs */
.cf-hover-underline {
  position: relative;
  text-decoration: none;
}
.cf-hover-underline::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--cf-amber);
  transition: width 250ms cubic-bezier(0.16, 1, 0.3, 1);
}
.cf-hover-underline:hover::after {
  width: 100%;
}

/* Button press — subtle scale on active */
.cf-hover-press:active {
  transform: scale(0.98);
  transition: transform 100ms ease;
}

/* Image reveal on hover for photo contexts */
.cf-hover-reveal {
  overflow: hidden;
}
.cf-hover-reveal img {
  transition: transform 400ms cubic-bezier(0.16, 1, 0.3, 1);
}
.cf-hover-reveal:hover img {
  transform: scale(1.03);
}


/* --- Transition utilities --- */
/* For elements that change state (open/close, toggle, etc) */

.cf-transition-fast   { transition: all 100ms ease; }
.cf-transition-base   { transition: all 150ms ease; }
.cf-transition-slow   { transition: all 300ms ease; }
.cf-transition-color  { transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; }
.cf-transition-opacity { transition: opacity 200ms ease; }
.cf-transition-transform { transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1); }


/* --- Reduced motion --- */
/* Always respect system preference */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .cf-reveal {
    opacity: 1;
  }
}


/*
   JS SNIPPET — IntersectionObserver for .cf-reveal elements
   Add to your main JS file or inline at bottom of <body>
   
   -------------------------------------------------------
   const reveals = document.querySelectorAll('.cf-reveal');
   const observer = new IntersectionObserver((entries) => {
     entries.forEach(entry => {
       if (entry.isIntersecting) {
         entry.target.classList.add('is-visible');
         observer.unobserve(entry.target);
       }
     });
   }, { threshold: 0.12, rootMargin: '0px 0px -48px 0px' });
   reveals.forEach(el => observer.observe(el));
   -------------------------------------------------------
*/


/* ============================================================
   2. GRID FRAMEWORK
   ============================================================
   
   Philosophy: editorial grid, not a utility framework.
   Built for content layouts — articles, card listings,
   sidebars, and hero sections. Responsive by default.
   
   Container sizes match the design system max-width tokens.
   
   Usage:
   <div class="cf-grid cf-grid-2">...</div>
   <div class="cf-grid cf-grid-3">...</div>
   ============================================================ */


/* --- Grid containers --- */

.cf-grid {
  display: grid;
  gap: var(--cf-space-7);
}

/* Two column — card pairs, side-by-side sections */
.cf-grid-2 {
  grid-template-columns: repeat(2, 1fr);
}

/* Three column — article card listings */
.cf-grid-3 {
  grid-template-columns: repeat(3, 1fr);
}

/* Four column — tag clouds, minimal listings */
.cf-grid-4 {
  grid-template-columns: repeat(4, 1fr);
}

/* Auto-fill — responsive without breakpoints, min 280px per cell */
.cf-grid-auto {
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* Auto-fill tight — min 200px, for tag-sized elements */
.cf-grid-auto-tight {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}


/* --- Editorial layouts --- */

/* Main + sidebar — 2:1 ratio */
.cf-grid-sidebar {
  grid-template-columns: 1fr 320px;
  gap: var(--cf-space-8);
}

/* Wide main + narrow sidebar — 3:1 ratio */
.cf-grid-sidebar-narrow {
  grid-template-columns: 1fr 240px;
  gap: var(--cf-space-8);
}

/* Hero layout — large left, stacked right */
.cf-grid-hero {
  grid-template-columns: 3fr 2fr;
  gap: var(--cf-space-7);
}

/* Full bleed — single column, no max-width restriction */
.cf-grid-full {
  grid-template-columns: 1fr;
}

/* Asymmetric — editorial feature layout */
.cf-grid-asymmetric {
  grid-template-columns: 2fr 1fr;
  gap: var(--cf-space-7);
}


/* --- Gap modifiers --- */

.cf-gap-tight  { gap: var(--cf-space-4); }
.cf-gap-base   { gap: var(--cf-space-6); }
.cf-gap-loose  { gap: var(--cf-space-7); }
.cf-gap-wide   { gap: var(--cf-space-9); }
.cf-gap-none   { gap: 0; }

/* Column and row gap separately */
.cf-col-gap-tight  { column-gap: var(--cf-space-4); }
.cf-col-gap-base   { column-gap: var(--cf-space-6); }
.cf-col-gap-loose  { column-gap: var(--cf-space-7); }
.cf-row-gap-tight  { row-gap: var(--cf-space-4); }
.cf-row-gap-base   { row-gap: var(--cf-space-6); }
.cf-row-gap-loose  { row-gap: var(--cf-space-7); }


/* --- Span utilities --- */
/* Use inside any cf-grid-* parent */

.cf-span-2 { grid-column: span 2; }
.cf-span-3 { grid-column: span 3; }
.cf-span-4 { grid-column: span 4; }
.cf-span-full { grid-column: 1 / -1; }
.cf-row-span-2 { grid-row: span 2; }


/* --- Flex layout utilities --- */
/* Complements the grid for inline and row-based layouts */

.cf-flex-row {
  display: flex;
  flex-direction: row;
  gap: var(--cf-space-5);
}

.cf-flex-col {
  display: flex;
  flex-direction: column;
  gap: var(--cf-space-4);
}

.cf-flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

.cf-flex-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.cf-flex-start {
  display: flex;
  align-items: flex-start;
}

.cf-flex-wrap {
  flex-wrap: wrap;
}

.cf-flex-1 { flex: 1; }
.cf-flex-none { flex: none; }
.cf-flex-shrink-0 { flex-shrink: 0; }


/* --- Alignment utilities --- */

.cf-align-start   { align-items: flex-start; }
.cf-align-center  { align-items: center; }
.cf-align-end     { align-items: flex-end; }
.cf-justify-start { justify-content: flex-start; }
.cf-justify-center { justify-content: center; }
.cf-justify-end   { justify-content: flex-end; }
.cf-self-start    { align-self: flex-start; }
.cf-self-end      { align-self: flex-end; }
.cf-self-center   { align-self: center; }


/* --- Grid responsive breakpoints --- */

@media (max-width: 1024px) {
  .cf-grid-3 {
    grid-template-columns: repeat(2, 1fr);
  }

  .cf-grid-4 {
    grid-template-columns: repeat(2, 1fr);
  }

  .cf-grid-sidebar {
    grid-template-columns: 1fr 280px;
  }

  .cf-grid-hero {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 768px) {
  .cf-grid-2,
  .cf-grid-3,
  .cf-grid-4,
  .cf-grid-sidebar,
  .cf-grid-sidebar-narrow,
  .cf-grid-hero,
  .cf-grid-asymmetric {
    grid-template-columns: 1fr;
  }

  .cf-span-2,
  .cf-span-3,
  .cf-span-4 {
    grid-column: span 1;
  }

  .cf-grid {
    gap: var(--cf-space-5);
  }

  .cf-flex-row {
    flex-direction: column;
    gap: var(--cf-space-4);
  }
}


/* ============================================================
   3. DARK MODE
   ============================================================
   
   Philosophy: dark mode inverts the canvas but preserves
   the structural identity. The amber accent intensifies
   slightly for contrast. The signature bar becomes white.
   The warm off-white becomes a dark warm surface.
   
   Activation:
   - System preference: automatic via prefers-color-scheme
   - Manual toggle: add data-theme="dark" to <html> or <body>
   
   Both methods work simultaneously. Manual toggle wins
   if present regardless of system preference.
   ============================================================ */

/* --- System preference --- */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --cf-black:       #F0EDE8;   /* Inverted: light text on dark */
    --cf-amber:       #D4893A;   /* Slightly warmer amber for dark contrast */
    --cf-amber-light: #3A2A14;   /* Amber tint inverted to dark */
    --cf-white:       #141210;   /* Near black canvas */
    --cf-warm:        #1C1A17;   /* Dark warm surface for newsletter */
    --cf-grey-100:    #201E1B;   /* Dark surface */
    --cf-grey-200:    #2E2B27;   /* Dark borders */
    --cf-grey-400:    #6B6560;   /* Muted text */
    --cf-grey-600:    #9B958E;   /* Secondary text */
    --cf-grey-800:    #C8C2BB;   /* Body text on dark */
  }
}

/* --- Manual toggle --- */
/* Add data-theme="dark" to <html> to force dark mode */
/* Add data-theme="light" to <html> to force light mode */

[data-theme="dark"] {
  --cf-black:       #F0EDE8;
  --cf-amber:       #D4893A;
  --cf-amber-light: #3A2A14;
  --cf-white:       #141210;
  --cf-warm:        #1C1A17;
  --cf-grey-100:    #201E1B;
  --cf-grey-200:    #2E2B27;
  --cf-grey-400:    #6B6560;
  --cf-grey-600:    #9B958E;
  --cf-grey-800:    #C8C2BB;
}

[data-theme="light"] {
  --cf-black:       #1A1A1A;
  --cf-amber:       #BA7517;
  --cf-amber-light: #F5E6C8;
  --cf-white:       #FFFFFF;
  --cf-warm:        #F5F2EC;
  --cf-grey-100:    #F0EDEA;
  --cf-grey-200:    #E0DDD8;
  --cf-grey-400:    #AAAAAA;
  --cf-grey-600:    #666666;
  --cf-grey-800:    #333333;
}


/* --- Dark mode component overrides --- */
/* Elements that need targeted adjustments beyond token swaps */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body {
    background-color: var(--cf-white);
    color: var(--cf-grey-800);
  }

  /* Nav border lightens */
  :root:not([data-theme="light"]) .cf-nav {
    border-bottom-color: var(--cf-grey-200);
  }

  /* Inputs get dark backgrounds */
  :root:not([data-theme="light"]) .cf-input,
  :root:not([data-theme="light"]) .cf-textarea,
  :root:not([data-theme="light"]) .cf-select {
    background: var(--cf-grey-100);
    border-color: var(--cf-grey-200);
    color: var(--cf-black);
  }

  :root:not([data-theme="light"]) .cf-input::placeholder,
  :root:not([data-theme="light"]) .cf-textarea::placeholder {
    color: var(--cf-grey-400);
  }

  /* Cards use dark surface */
  :root:not([data-theme="light"]) .cf-card-surface {
    background: var(--cf-grey-100);
  }

  /* Newsletter warm background shifts to dark warm */
  :root:not([data-theme="light"]) .cf-newsletter {
    background: var(--cf-warm);
  }

  /* Select dropdown arrow colour */
  :root:not([data-theme="light"]) .cf-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23F0EDE8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  }

  /* Reference page sidebar in dark */
  :root:not([data-theme="light"]) .ref-sidebar {
    background: var(--cf-grey-100);
    border-right-color: var(--cf-grey-200);
  }
}

/* Same overrides for manual [data-theme="dark"] */
[data-theme="dark"] body {
  background-color: var(--cf-white);
  color: var(--cf-grey-800);
}

[data-theme="dark"] .cf-nav {
  border-bottom-color: var(--cf-grey-200);
}

[data-theme="dark"] .cf-input,
[data-theme="dark"] .cf-textarea,
[data-theme="dark"] .cf-select {
  background: var(--cf-grey-100);
  border-color: var(--cf-grey-200);
  color: var(--cf-black);
}

[data-theme="dark"] .cf-input::placeholder,
[data-theme="dark"] .cf-textarea::placeholder {
  color: var(--cf-grey-400);
}

[data-theme="dark"] .cf-card-surface {
  background: var(--cf-grey-100);
}

[data-theme="dark"] .cf-newsletter {
  background: var(--cf-warm);
}

[data-theme="dark"] .cf-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23F0EDE8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}


/* --- Dark mode toggle button --- */
/*
   Example toggle button. Wire up with the JS snippet below.
   Place anywhere in your nav or page.
   
   <button class="cf-theme-toggle" aria-label="Toggle dark mode">
     <span class="cf-theme-icon-light">&#9788;</span>
     <span class="cf-theme-icon-dark">&#9790;</span>
   </button>
*/

.cf-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  background: transparent;
  border: 1px solid var(--cf-grey-200);
  cursor: pointer;
  transition: border-color 150ms ease;
  font-size: 14px;
  color: var(--cf-grey-600);
  border-radius: 0;
}
.cf-theme-toggle:hover {
  border-color: var(--cf-black);
  color: var(--cf-black);
}

/* Show/hide appropriate icon based on current theme */
.cf-theme-icon-dark { display: none; }

[data-theme="dark"] .cf-theme-icon-light { display: none; }
[data-theme="dark"] .cf-theme-icon-dark  { display: inline; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .cf-theme-icon-light { display: none; }
  :root:not([data-theme="light"]) .cf-theme-icon-dark  { display: inline; }
}


/*
   JS SNIPPET — Dark mode toggle
   Add to your main JS file or inline at bottom of <body>
   
   -------------------------------------------------------
   const toggle = document.querySelector('.cf-theme-toggle');
   const html   = document.documentElement;
   
   // Restore saved preference
   const saved = localStorage.getItem('cf-theme');
   if (saved) html.setAttribute('data-theme', saved);
   
   // Toggle on click
   toggle?.addEventListener('click', () => {
     const current = html.getAttribute('data-theme');
     const next = current === 'dark' ? 'light' : 'dark';
     html.setAttribute('data-theme', next);
     localStorage.setItem('cf-theme', next);
   });
   -------------------------------------------------------
*/
