/* ==========================================================================
   Conficore — foundation layer
   Sits on top of tokens.css. The exported design system ships zero media
   queries and no motion; everything responsive, motion, and a11y lives here.
   ========================================================================== */

/* --- Contrast correction ------------------------------------------------
   --brand-yellow on white measures 1.38:1 and --brand-yellow-dark 1.81:1.
   WCAG AA needs 4.5:1 for normal text. The yellow stays the brand colour for
   fills and accents; these tokens are for yellow *text on light surfaces*. */
:root {
  --accent-text-on-light: #6b6a12;  /* 5.68:1 on white   — AA pass */
  --accent-text-on-alt:   #67660f;  /* 5.77:1 on paper-50 — AA pass */

  /* Every use of --brand-yellow-dark across the DS and both page modules (13
     call sites) is `color:` on an uppercase eyebrow over a light surface —
     never a fill. Redefining it here fixes all of them at once. The untouched
     --brand-yellow still drives buttons, rules, and on-dark accents. */
  --brand-yellow-dark: var(--accent-text-on-light);

  /* Muted body copy failed AA too: --text-muted resolved to --slate-400
     (#8d9794, 3.01:1) and the DS caption style to --slate-500 (#6b7774,
     3.88:1).
     --text-muted is retargeted rather than --slate-400 itself, because
     --border-strong also points at --slate-400 and borders should not darken.
     #67716e -> 5.04:1 on white, 4.83:1 on --paper-50.
     --slate-500's only consumer is the VideoFrame caption, which sits on the
     --slate-100 placeholder tint (#e9ebea) — the darkest light surface in the
     system — so it needs a darker value: #5d6764 -> 4.89:1 there, 5.85:1 on white. */
  --text-muted: #67716e;
  --slate-500: #5d6764;

  --nav-height: 88px;
  --nav-height-sm: 68px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 180ms;
  --dur-mid: 420ms;
  --dur-slow: 720ms;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  /* Sticky nav must not cover in-page anchor targets. */
  scroll-padding-top: var(--nav-height);
}

img, video, svg { max-width: 100%; }

/* --- Focus: visible, never removed --------------------------------------
   The brand yellow ring is invisible on white, so ink is the default and
   yellow is used only on dark surfaces. */
:focus-visible {
  outline: 3px solid var(--ink-900);
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

[data-dark] :focus-visible,
.cf-on-dark :focus-visible { outline-color: var(--brand-yellow); }

/* --- Skip link ----------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: 12px; top: -100px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--ink-900);
  color: var(--paper-0);
  font-weight: var(--weight-semibold);
  border-radius: 999px;
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus { top: 12px; }

/* ==========================================================================
   Responsive grid collapse
   The exported sections hard-code repeat(4,1fr) / repeat(3,1fr) / 1fr 1fr as
   inline styles. Inline styles beat stylesheet rules, so these overrides need
   !important — the alternative is rewriting every section's inline style.
   ========================================================================== */

/* Grid items default to a min-content minimum, so an `fr` track can't shrink
   below its widest child. The <image-slot> custom element reports a wide
   min-content, which pushed the Gallery's `1.4fr 1fr 1fr` out to 1356px inside
   a 1205px container — 89px of horizontal page overflow on every vertical page,
   present since the original export. min-width:0 lets the tracks shrink. */
main [style*="grid-template-columns"] > *,
main [style*="grid-template-rows"] > * { min-width: 0; }
image-slot { min-width: 0; }

/* Tablet — 4-up and 3-up both become 2-up. */
@media (max-width: 1024px) {
  [style*="repeat(4,1fr)"],
  [style*="repeat(4, 1fr)"],
  [style*="repeat(3,1fr)"],
  [style*="repeat(3, 1fr)"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  /* Asymmetric editorial splits stack at tablet. */
  [style*="0.9fr 1.1fr"],
  [style*="1.4fr 1fr 1fr"] {
    grid-template-columns: 1fr !important;
    grid-template-rows: auto !important;
  }
  [style*="1.4fr 1fr 1fr"] > * { grid-row: auto !important; height: 260px !important; }
}

/* Mobile — everything single column. */
@media (max-width: 720px) {
  [style*="grid-template-columns"],
  [style*="gridTemplateColumns"] {
    grid-template-columns: 1fr !important;
  }
  [style*="1.4fr 1fr 1fr"] > * { height: 220px !important; }

  /* Reclaim horizontal padding. */
  section { padding-left: 20px !important; padding-right: 20px !important; }

  /* Hero: 92vh is too tall next to mobile browser chrome. */
  section[style*="92vh"], section[style*="80vh"] {
    height: auto !important;
    min-height: 78svh !important;
    padding-top: 96px !important;
    padding-bottom: 48px !important;
  }

  /* The desktop scrim ramps by percentage of hero height, which assumes the
     copy sits in the bottom third. Once the hero shrinks, the copy spans
     roughly 49-84% of it and lands in the light part of that ramp — measured
     against the video's brightest frames the eyebrow fell to 2.35:1. Flatter
     and stronger here; the footage still reads through it. */
  .cf-hero-scrim {
    background: linear-gradient(0deg,
      rgba(20, 24, 26, 0.95) 0%,
      rgba(20, 24, 26, 0.90) 55%,
      rgba(20, 24, 26, 0.82) 100%) !important;
  }
}

/* --- Fluid type ----------------------------------------------------------
   The display scale is fixed px in tokens.css, which overflows small screens. */
@media (max-width: 900px) {
  :root {
    --text-display-1: clamp(2.75rem, 11vw, 5rem);
    --text-display-2: clamp(2.25rem, 9vw, 4rem);
    --text-h1: clamp(1.875rem, 6.5vw, 3rem);
    --text-h2: clamp(1.5rem, 5vw, 2.25rem);
  }
  body { font-size: 1rem; line-height: 1.6; }
}

/* ==========================================================================
   Motion — fade, slide, image reveal, hovers.
   Applied by src/lib/motion.js via [data-reveal].
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  will-change: opacity, transform;
}
[data-reveal="left"]  { transform: translateX(-28px); }
[data-reveal="right"] { transform: translateX(28px); }
[data-reveal="scale"] { transform: scale(0.96); }

[data-reveal].is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Stagger children of a revealed group. */
[data-reveal-group] > * { transition-delay: calc(var(--i, 0) * 90ms); }

/* Image reveal — a wipe rather than a fade. */
.reveal-clip { clip-path: inset(0 0 100% 0); transition: clip-path var(--dur-slow) var(--ease-out); }
.reveal-clip.is-visible { clip-path: inset(0 0 0 0); }

/* Hover: cards lift, buttons settle. Pointer-capable devices only. */
@media (hover: hover) and (pointer: fine) {
  [data-card] {
    transition: transform var(--dur-mid) var(--ease-out),
                box-shadow var(--dur-mid) var(--ease-out),
                border-color var(--dur-mid) var(--ease-out);
  }
  [data-card]:hover {
    transform: translateY(-6px);
    box-shadow: 0 18px 44px rgba(20, 24, 26, 0.13);
    border-color: var(--border-strong);
  }
  button, [role="button"], a[data-cta] {
    transition: transform var(--dur-fast) var(--ease-out),
                background-color var(--dur-fast) var(--ease-out),
                color var(--dur-fast) var(--ease-out);
  }
  button:hover, [role="button"]:hover, a[data-cta]:hover { transform: translateY(-2px); }
  button:active, [role="button"]:active { transform: translateY(0); }
}

/* Parallax depth, driven by motion.js. */
[data-parallax] { will-change: transform; }

/* --- Respect reduced-motion --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .reveal-clip { clip-path: none !important; }
  [data-parallax] { transform: none !important; }
}

/* ==========================================================================
   Sticky mobile CTA — brief: "Sticky CTA" under Mobile Experience.
   ========================================================================== */
.mobile-cta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: none;
  gap: 10px;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--border-subtle);
}
.mobile-cta > * { flex: 1; }

@media (max-width: 720px) {
  .mobile-cta { display: flex; }
  body { padding-bottom: 76px; }
}

/* ==========================================================================
   Print
   ========================================================================== */
@media print {
  header, .mobile-cta, .skip-link { display: none !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}
