/* ==========================================================================
   Koheso — Variant V11h: Mono + Gradient
   V11 (Keynote White), stripped of all product colour. The page is ink,
   graphite and silver — machined, dimensional, monochrome — except for
   exactly three gradient moments per product: the hero wordmark (unchanged),
   one key word inside the product statement, and a hairline rule under the
   kicker. Scarcity is the luxury: on an otherwise achromatic page, those
   three gradient touches read like jewellery. Vanilla CSS, no framework.
   ========================================================================== */

/* -------------------------------------------------------------------------
   Fonts — shared, already-deployed Outfit variable font
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Outfit";
  src: url("/assets/fonts/outfit-variable.woff2") format("woff2");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}

/* -------------------------------------------------------------------------
   Custom properties
   ------------------------------------------------------------------------- */
:root {
  --font-sans: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* neutrals — near-white ground, near-black ink */
  --paper: #fcfcfa;
  --surface: #ffffff;
  --ink: #0b0b0f;
  --ink-soft: #63636d;
  --ink-faint: #9a9aa2;
  --line: rgba(11, 11, 15, 0.08);

  /* machined-object grayscale — the only palette the product renders use.
     Runs specular white through silver/steel to a graphite/carbon floor,
     giving the objects dimensional life without a trace of hue. */
  --g-0: #ffffff;
  --g-50: #f4f5f6;
  --g-100: #e7e8eb;
  --g-200: #d2d4d8;
  --g-300: #aeb1b7;
  --g-400: #83868d;
  --g-500: #55575e;
  --g-600: #33343a;
  --g-700: #1a1b1f;

  /* the three gradient moments — one two-stop pair per product, AA-checked
     (>=4.5:1) at both stops against --paper. Used only for: the hero
     wordmark (separate, wider set below), each product's key word, and
     the hairline rule under each kicker. Nowhere else on the page. */
  --grid-1: #0a7656;   /* emerald */
  --grid-2: #0d7080;   /* cyan */
  --atrium-1: #c11596; /* magenta */
  --atrium-2: #a83e08; /* amber */
  --time-1: #143db0;   /* cobalt */
  --time-2: #5b3fd6;   /* violet */

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --header-h: 4.5rem;

  --container: 72rem;
}

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

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

body,
h1,
h2,
p,
figure {
  margin: 0;
}

html {
  /* clip, not hidden: hidden would make body a scroll container and
     break position: sticky on the header */
  overflow-x: clip;
}

body {
  font-family: var(--font-sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: inherit;
}

/* -------------------------------------------------------------------------
   Accessibility helpers
   ------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: -100%;
  left: 1rem;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--surface);
  border-radius: 0.5rem;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s var(--ease-out);
}

.skip-link:focus {
  top: 1rem;
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* -------------------------------------------------------------------------
   Header / nav — minimal, wordmark + three anchors
   ------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(252, 252, 250, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}

.header-inner {
  max-width: var(--container);
  margin: 0 auto;
  height: var(--header-h);
  padding: 0 clamp(1.25rem, 4vw, 3rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  font-size: 1.0625rem;
  text-decoration: none;
  color: var(--ink);
}

/* The header mark: ko-ink geometry (shipped F9b), sized off the anchor's
   own font-size so it scales if that value ever changes. Ratio (0.75em)
   matches the ink-height of the text it replaced (measured via canvas
   actualBoundingBox at the old 700-weight/17px setting), not the full
   em-box, so the swap doesn't change the header's visual weight. */
.wordmark-mark {
  display: block;
  height: 0.75em;
  width: auto;
  fill: currentColor;
}

.site-nav {
  display: flex;
  gap: clamp(1.25rem, 3vw, 2.25rem);
}

.site-nav a {
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink-soft);
  transition: color 0.2s var(--ease-out);
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--ink);
}

/* -------------------------------------------------------------------------
   Section chassis — one product per full viewport, generous breathing room
   ------------------------------------------------------------------------- */
main {
  display: block;
}

.hero,
.product {
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100svh - var(--header-h));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(3rem, 8vh, 6rem) clamp(1.25rem, 6vw, 3rem);
  scroll-margin-top: var(--header-h);
}

/* Platform sections: tighter vertical pacing than the hero — the
   between-platform whitespace is deliberately ~40% less than the
   original full-viewport centering produced (client direction). */
.product {
  min-height: calc(85vh - var(--header-h));
  min-height: calc(85svh - var(--header-h));
  padding-top: clamp(1.8rem, 4.8vh, 3.6rem);
  padding-bottom: clamp(1.8rem, 4.8vh, 3.6rem);
}

.hero-inner,
.product-inner {
  max-width: 46rem;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* -------------------------------------------------------------------------
   Typography
   ------------------------------------------------------------------------- */
.kicker {
  position: relative;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 1.625rem;
}

/* Gradient moment 1 of 3: a hairline rule under each kicker, the section's
   only trace of colour besides its key word below. Pseudo-element (not a
   sibling node) so it inherits the reveal fade of .kicker without disturbing
   the .reveal:nth-child() stagger timing on the elements after it. */
.kicker::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -0.75rem;
  transform: translateX(-50%);
  width: 1.75rem;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--grad-a, var(--ink-faint)), var(--grad-b, var(--ink-faint)));
}

/* Gradient moment 2 of 3: exactly one key word per product statement.
   Falls back to solid ink for browsers without background-clip: text. */
.grad-word {
  font-weight: inherit;
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .grad-word {
    background-image: linear-gradient(100deg, var(--grad-a, var(--ink)), var(--grad-b, var(--ink)));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* Per-product gradient tokens (moved from inline style attributes so a
   strict CSP needs no style-src 'unsafe-inline') */
#grid {
  --grad-a: var(--grid-1);
  --grad-b: var(--grid-2);
}

#atrium {
  --grad-a: var(--atrium-1);
  --grad-b: var(--atrium-2);
}

#time {
  --grad-a: var(--time-1);
  --grad-b: var(--time-2);
}

/* Strong brand wordmark in the hero — the shipped F9b mark (ko-fill,
   13.19u solved spacing), rendered as an inline SVG with its own 13-stop
   tri-product gradient baked into a <linearGradient> (see the svg markup
   above). .hero-brand keeps only the layout properties: font-size drives
   the mark's em-relative size below, margin-bottom holds its position in
   the hero stack. Static gradient — see the shipped-static note in
   graphics/README.md; no background-clip/text-fill properties remain, so
   there's nothing here that needs a @supports fallback. */
.hero-brand {
  display: inline-block;
  font-size: clamp(2.5rem, 4.5vw, 5rem);
  line-height: 1;
  margin-bottom: 1.5rem;
}

/* Ratio (0.75em) matches the ink-height of the text this mark replaced
   (measured via canvas actualBoundingBox at the old 700-weight setting),
   not the full em-box, so the swap doesn't change the hero's visual scale. */
.hero-brand-mark {
  display: block;
  height: 0.75em;
  width: auto;
}

.hero-title {
  font-size: clamp(2.5rem, 3.2vw + 1.6rem, 4.75rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.hero-caption {
  margin-top: 1.5rem;
  font-size: clamp(1rem, 0.4vw + 0.9rem, 1.1875rem);
  font-weight: 400;
  color: var(--ink-soft);
  max-width: 34rem;
  line-height: 1.55;
}

.product-statement {
  font-size: clamp(1.875rem, 2.4vw + 1.2rem, 3.5rem);
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin-top: clamp(2rem, 5vw, 3.5rem);
}

.product-caption {
  margin-top: 1.125rem;
  font-size: 1.0625rem;
  color: var(--ink-soft);
  max-width: 30rem;
  line-height: 1.6;
}

/* "Coming soon" as an ink-outline chip — no colour, so it never competes
   with the section's two gradient moments. */
.soon {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.1875rem 0.6875rem;
  vertical-align: 0.0625rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  border: 1px solid var(--ink-faint);
  border-radius: 999px;
  white-space: nowrap;
}

.scroll-cue {
  margin-top: clamp(2.5rem, 6vh, 4rem);
  /* --ink-soft, not --ink-faint: interactive control needs 3:1 (WCAG 1.4.11) */
  color: var(--ink-soft);
  transition: color 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}

.scroll-cue svg {
  width: 1.5rem;
  height: 1.5rem;
}

.scroll-cue:hover,
.scroll-cue:focus-visible {
  color: var(--ink);
  transform: translateY(3px);
}

/* -------------------------------------------------------------------------
   Scroll reveal — transform + opacity only, calm, no bounce
   ------------------------------------------------------------------------- */
/* Hidden-then-revealed only when JS is running (main.js adds .js to <html>).
   Without JS every .reveal renders visible — no content blackout. */
html.js .reveal {
  opacity: 0;
  transform: translateY(28px) scale(0.98);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}

.hero.is-visible .reveal,
.product.is-visible .reveal {
  opacity: 1;
  transform: none;
}

.hero.is-visible .reveal:nth-child(2),
.product.is-visible .reveal:nth-child(2) {
  transition-delay: 0.09s;
}

.hero.is-visible .reveal:nth-child(3),
.product.is-visible .reveal:nth-child(3) {
  transition-delay: 0.18s;
}

.hero.is-visible .reveal:nth-child(4),
.product.is-visible .reveal:nth-child(4) {
  transition-delay: 0.27s;
}

/* -------------------------------------------------------------------------
   Product objects — shared frame
   ------------------------------------------------------------------------- */
.product-object {
  position: relative;
  width: clamp(190px, 24vw, 320px);
  height: clamp(190px, 24vw, 320px);
  margin: 0 auto;
}

.object-shadow {
  position: absolute;
  left: 50%;
  bottom: -6%;
  width: 68%;
  height: 10%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(15, 15, 25, 0.2), rgba(15, 15, 25, 0));
  filter: blur(3px);
  border-radius: 50%;
}

/* --- Grid: floating machined tile stack ---------------------------------
   Every hue is gone — depth now comes purely from a silver-to-steel value
   ramp plus neutral ink-tinted shadows (rgba(20,20,24,*) throughout). */
.tile {
  position: absolute;
  inset: 9%;
  border-radius: 22%;
  background: linear-gradient(155deg, var(--g-0) 0%, var(--g-50) 55%, var(--g-200) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -10px 22px rgba(20, 20, 24, 0.12),
    0 30px 46px -18px rgba(20, 20, 24, 0.34);
}

.tile::before {
  content: "";
  position: absolute;
  top: 8%;
  left: 10%;
  width: 42%;
  height: 34%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0));
  border-radius: 50%;
}

.tile--back {
  transform: translate(-19%, 15%) rotate(-10deg) scale(0.86);
  background: linear-gradient(155deg, var(--g-100) 0%, var(--g-300) 60%, var(--g-400) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.75),
    inset 0 -10px 22px rgba(20, 20, 24, 0.2),
    0 22px 34px -14px rgba(20, 20, 24, 0.4);
}

.tile--mid {
  transform: translate(-9.5%, 7.5%) rotate(-5deg) scale(0.93);
  background: linear-gradient(155deg, var(--g-50) 0%, var(--g-200) 60%, var(--g-300) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -10px 22px rgba(20, 20, 24, 0.16),
    0 26px 38px -16px rgba(20, 20, 24, 0.36);
}

.tile--front {
  transform: translate(0, 0) rotate(0deg);
}

.tile__motif {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* --- Atrium: arched portal slab ------------------------------------------ */
.arch {
  position: absolute;
  left: 50%;
  bottom: 7%;
  transform: translateX(-50%);
  background: linear-gradient(160deg, var(--g-0) 0%, var(--g-50) 55%, var(--g-200) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -10px 18px rgba(20, 20, 24, 0.14),
    0 26px 42px -18px rgba(20, 20, 24, 0.32);
}

.arch--outer {
  width: 78%;
  height: 86%;
  border-radius: 50% 50% 0 0 / 42% 42% 0 0;
}

.arch--mid {
  width: 55%;
  height: 63%;
  border-radius: 50% 50% 0 0 / 42% 42% 0 0;
  background: linear-gradient(160deg, var(--g-50) 0%, var(--g-200) 100%);
  box-shadow:
    inset 0 10px 18px rgba(20, 20, 24, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* The portal's dark throat — graphite falling to carbon. This is the
   deepest tone on the page, doing the same job the accent hue used to:
   giving the object a believable core without spending any colour on it. */
.arch--inner {
  width: 32%;
  height: 40%;
  border-radius: 50% 50% 0 0 / 42% 42% 0 0;
  background: linear-gradient(160deg, var(--g-500) 0%, var(--g-700) 100%);
  box-shadow: inset 0 6px 14px rgba(0, 0, 0, 0.45);
}

/* --- Time: machined ring / dial ------------------------------------------ */
.ring {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 26%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 42%),
    conic-gradient(from 200deg, var(--g-50), var(--g-200), var(--g-50), var(--g-100), var(--g-50));
  box-shadow:
    inset 0 2px 4px rgba(255, 255, 255, 0.9),
    inset 0 -10px 20px rgba(20, 20, 24, 0.2),
    0 28px 44px -16px rgba(20, 20, 24, 0.34);
}

.ring__ticks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.ring__face {
  position: absolute;
  inset: 23%;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--g-0) 0%, var(--g-100) 100%);
  box-shadow:
    inset 0 4px 10px rgba(20, 20, 24, 0.22),
    inset 0 -2px 4px rgba(255, 255, 255, 0.85);
}

.ring__hand {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 5%;
  height: 30%;
  border-radius: 3px;
  background: linear-gradient(var(--g-600), var(--g-700));
  transform-origin: 50% 100%;
  transform: translate(-50%, -100%) rotate(35deg);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
}

.ring__cap {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9%;
  height: 9%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle at 35% 30%, #ffffff, var(--g-700) 75%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* -------------------------------------------------------------------------
   Footer
   ------------------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 2rem clamp(1.25rem, 6vw, 3rem);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  font-size: 0.875rem;
  /* --ink-soft, not --ink-faint: 14px body text needs 4.5:1 (WCAG 1.4.3) */
  color: var(--ink-soft);
}



/* -------------------------------------------------------------------------
   Reduced motion — everything renders in its final state instantly
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .scroll-cue,
  .site-nav a {
    transition: none;
  }
}

/* -------------------------------------------------------------------------
   Small screens
   ------------------------------------------------------------------------- */
@media (max-width: 30rem) {
  .site-nav {
    gap: 1rem;
  }

  .site-nav a {
    font-size: 0.875rem;
  }
}

/* -------------------------------------------------------------------------
   Print — reveal everything; scroll state is meaningless on paper
   ------------------------------------------------------------------------- */
@media print {
  html.js .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* -------------------------------------------------------------------------
   Hero logo colour drift — the original hue-drift sweep, rebuilt for the
   SVG logo: a 3.4x-wide gradient layer pans behind the clipped wordmark.
   Under reduced motion the animated layer hides and the static full-sweep
   gradient beneath it shows instead.
   ------------------------------------------------------------------------- */
.hb-grad-anim {
  animation: hb-drift 26s ease-in-out infinite alternate;
}

@keyframes hb-drift {
  from { transform: translateX(0); }
  to { transform: translateX(-6666.7px); }
}

@media (prefers-reduced-motion: reduce) {
  .hb-grad-anim {
    display: none;
  }
}
