/* ============================================================
   KompanyOS — shared hero + Grind-walkthrough layer
   Used by index.html (light, default), dark.html (dark) and green.html.
   Only the GROUND (body bg, .net mesh, .pixels/.ground green flood) is
   variant-specific and lives inline in each file. Everything here — the
   software window, the abstracted "app" walkthrough, the title tape +
   sticker, the intro choreography and the reduced-motion fallback — is
   identical across the three so they never drift.
   Expects each file's :root to define: --white --ink --black --green
   --pink --gray-500 --gray-200 --font --mono --ease-bounce --shadow-sm.
   Optional per-variant: --win-shadow (hard offset shadow; light sets it).
   ============================================================ */

/* ---------- Shared grid + type-density spine (3 Sided Cube) ----------
   3sidedcube.com sits every background on ONE 40px cell: line grids as
   rgba(180,180,180,.3) 1px hairlines, dot patterns as 1.5px radius dots on
   the same 40px pitch (only the dot tint changes per ground). These tokens
   are the single source of truth — the per-variant grounds (body bg, .ground
   flood) and the window's inner desktop all read from them, so the grid never
   drifts between the three pages. A ground overrides just --dot-color to tint
   its dots; everything else stays put. Tune the numbers live in styles.html. */
:root {
  --grid-cell:   40px;                  /* master grid pitch — lines AND dots */
  --grid-line:   rgba(180,180,180,0.30);
  --grid-line-w: 1px;
  --dot-cell:    var(--grid-cell);
  --dot-r:       1.5px;                  /* dot radius */
  --dot-color:   rgba(208,208,208,0.56);/* 3SC gray-dot default; grounds retint */
  --grid-skew:   matrix(1.09933, -0.0383894, 0.0383894, 1.09933, 0, 0); /* the ground's signature tilt */

  /* Type density — Poppins display runs heavy + tight (matches the live site) */
  --trk-tight:   -0.02em;               /* display / headlines */
  --trk-kicker:   0.14em;               /* mono overlines, labels */
  --lh-display:   1.06;
  --lh-tight:     1.2;
}

/* Reusable line-grid + dot-grid any surface can opt into, both on the 40px
   cell. Grounds compose these instead of hand-rolling their own values. */
.kos-grid-lines {
  background-image:
    linear-gradient(var(--grid-line) var(--grid-line-w), transparent 0),
    linear-gradient(90deg, var(--grid-line) var(--grid-line-w), transparent 0);
  background-size: var(--grid-cell) var(--grid-cell), var(--grid-cell) var(--grid-cell);
}
.kos-grid-dots {
  background-image:
    radial-gradient(var(--dot-color) var(--dot-r), transparent 0),
    radial-gradient(var(--dot-color) var(--dot-r), transparent 0);
  background-position: 0 0, calc(var(--dot-cell) / 2) calc(var(--dot-cell) / 2);
  background-size: var(--dot-cell) var(--dot-cell), var(--dot-cell) var(--dot-cell);
}

/* Buttons + links now live in the shared components.css (link it on the page). */

.spacer { height: 240vh; }   /* real height set by hero.js from the timeline */

/* ---------- The product window: a pinned software surface ----------
   Rises from a bottom peek, widens, then PINS just below the menubar and
   stays put (its title bar never scrolls past the bar). Sizing driven by JS. */
.window {
  position: fixed; z-index: 20; left: 50%; top: 108vh;
  width: 58vw; height: calc(100vh - 74px);   /* fills from just below the 74px menubar to the viewport bottom */
  transform: translateX(-50%);
  display: flex; flex-direction: column;
  background: var(--white); color: var(--ink);
  border: 3px solid var(--black); border-radius: 20px;
  box-shadow: var(--win-shadow, none);
  overflow: hidden;
  will-change: top, width;
}
.titlebar { flex: none; display: flex; align-items: center; gap: 9px; padding: 16px 20px 12px; }
.light { width: 13px; height: 13px; border-radius: 50%; }
.light.r { background: #ff5f57; } .light.y { background: #febc2e; } .light.g { background: #28c840; }
/* section name mirrored into the titlebar once the header collapses (app name) */
.app-name { margin-left: 8px; font-family: var(--mono); font-weight: 700; text-transform: uppercase; letter-spacing: .12em;
  font-size: 13px; color: var(--ink); white-space: nowrap; opacity: 0; transform: translateX(-6px);
  transition: opacity .4s ease .05s, transform .45s var(--ease-bounce) .05s; }
.window.compact .app-name { opacity: 1; transform: none; }

/* ---------- Inside the window: the Grind as an abstracted app ----------
   Header (title + description) + a sidebar list of "what you're stuck doing"
   and a detail pane that reveals "what KompanyOS does instead" (text + an
   image placeholder). Scroll steps the active row (no free scroll). */
/* inner "desktop": 3 Sided Cube gray-dot pattern (bg-gray-dot-pattern, verbatim) */
.win-content { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  padding: clamp(14px, 2.2vh, 26px) clamp(24px, 4vw, 56px) clamp(18px, 2.6vh, 34px);
  background-color: #f5f5f5;
  /* 3SC gray-dot desktop, on the shared 40px grid cell */
  background-image:
    radial-gradient(var(--dot-color) var(--dot-r), transparent 0),
    radial-gradient(var(--dot-color) var(--dot-r), transparent 0);
  background-position: 0 0, calc(var(--dot-cell) / 2) calc(var(--dot-cell) / 2);
  background-size: var(--dot-cell) var(--dot-cell), var(--dot-cell) var(--dot-cell); }

/* header reveals when the window is grown. 3SC-style entrance choreography, in
   strict order: the title SPRINGS in with a scale bounce (ease-bounce overshoots
   past its rest, so it pops big then settles), TITLE LEADING; THEN the pink
   highlight tape WIPES in behind "you're the glue"; THEN the glue sticker bounces
   on. The body cards follow the header (see .app-body reveal). The container
   itself only animates layout (max-height). */
.app-head { flex: none; text-align: center; margin-bottom: clamp(26px, 4.5vh, 52px);
  max-height: 520px;
  transition: max-height .55s var(--ease-bounce), margin .45s ease; }
.app-head > * { opacity: 0; transform: translateY(-6px) scale(1.06);
  transition: opacity .45s ease, transform .75s var(--ease-bounce); }
/* the title drops in BIG and settles down (scale > 1 -> 1, bounces past) */
.app-head > .grind-title { transform: translateY(-6px) scale(1.15); }
.window.grown .grind-over  { opacity: 1; transform: none; transition-delay: .04s; }
.window.grown .grind-title { opacity: 1; transform: none; transition-delay: .14s; }
.window.grown .grind-sub   { opacity: 1; transform: none; transition-delay: .40s; }
/* the whole header (overline + glue title + description) stays visible through
   the walkthrough — nothing collapses; the titlebar just mirrors the name too */
/* once the header collapses, the two cards become a compact, vertically-centred
   panel on the dotted ground (rather than stretching to fill the whole window) */
.window.compact .app-body { flex: 0 1 auto; max-height: 62vh; margin-block: auto; }
.grind-over { font-family: var(--mono); font-weight: 700; text-transform: uppercase; letter-spacing: var(--trk-kicker); font-size: 12px; color: var(--gray-500); }
.grind-title { margin-top: 10px; font-size: clamp(26px, 2.8vw, 44px); font-weight: 800; letter-spacing: var(--trk-tight); line-height: var(--lh-display); color: var(--ink); }
/* pink "tape" highlight on "you're the glue" + glue-bottle sticker hung off the end.
   3SC-style: the words are present (dark, readable) as the title lands, THEN the
   pink tape WIPES in left-to-right behind them (background-size 0%->100%); the
   text flips to white just as the fill completes so it never sits white-on-white. */
.gt { position: relative; display: inline-block; color: var(--ink); padding: 0.02em 1.25em 0.02em 0.32em;
  background-image: linear-gradient(var(--pink), var(--pink));
  background-repeat: no-repeat; background-position: left center; background-size: 0% 100%; }
.window.grown .gt { background-size: 100% 100%; color: #fff;
  transition: background-size .5s cubic-bezier(0.22, 1, 0.36, 1) .72s, color .12s linear 1.10s; }
/* glue-bottle sticker bounces on LAST, once the highlight has landed */
.gt-sticker { position: absolute; right: -0.62em; top: 50%; height: 2.05em; width: auto;
  transform: translateY(-50%) rotate(9deg); transform-origin: center; pointer-events: none; opacity: 0; }
.window.grown .gt-sticker { animation: gt-sticker-pop .6s var(--ease-bounce) 1.14s both; }
@keyframes gt-sticker-pop {
  0%   { opacity: 0; transform: translateY(-50%) rotate(-26deg) scale(0.2); }
  55%  { opacity: 1; transform: translateY(-50%) rotate(14deg)  scale(1.14); }
  100% { opacity: 1; transform: translateY(-50%) rotate(9deg)   scale(1); }
}
.grind-sub { margin: 13px auto 0; max-width: 56ch; font-size: clamp(13px, 1vw, 16px); font-weight: 500; line-height: 1.5; color: var(--gray-500); }

/* the content follows the title in — cards reveal a beat after the header text */
.app-body { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(240px, 40%) 1fr; gap: clamp(18px, 3vw, 44px);
  opacity: 0; transform: translateY(20px);
  transition: opacity .55s ease, transform .65s var(--ease-bounce); }
.window.grown .app-body { opacity: 1; transform: none; transition-delay: .46s; }
.col-label { font-family: var(--mono); text-transform: uppercase; letter-spacing: var(--trk-kicker); font-size: 11px; color: var(--gray-500); margin-bottom: 12px; }

/* two 3SC cards on the dotted ground: left = white (problems), right = green (KompanyOS) */
.app-list, .app-detail { display: flex; flex-direction: column; min-height: 0;
  border: 1.5px solid #0f0f0f; border-radius: 16px; box-shadow: 5px 5px 0 0 rgba(0,0,0,0.92);
  padding: clamp(15px, 2.2vh, 22px) clamp(15px, 1.5vw, 20px); }
.app-list { background: var(--white); }
.app-detail { background: var(--green); overflow: visible; }
.app-detail .col-label { color: #0b3d24; }   /* dark label reads on green */

/* left list: circular icon slot + text; active row highlighted, passed rows filled green */
.app-list ul { list-style: none; flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; gap: clamp(2px, 0.7vh, 8px); }
.app-item { display: flex; gap: 13px; align-items: center; padding: 7px 12px; border-radius: 12px;
  color: var(--gray-500); font-size: clamp(13px, 1vw, 16px); line-height: 1.25; opacity: .5;
  transition: background .4s var(--ease-bounce), color .35s, opacity .35s, box-shadow .35s; }
.ai-ic { flex: none; width: clamp(30px, 2.6vw, 40px); height: clamp(30px, 2.6vw, 40px); border-radius: 50%;
  background: #e2e2e2; color: #8a8a8a; display: grid; place-items: center; font-weight: 700; font-size: clamp(12px, 1vw, 15px); }
.app-item.done { opacity: .7; }
.app-item.active { background: #fdeef6; color: var(--ink); opacity: 1; font-weight: 700; box-shadow: inset 3px 0 0 0 var(--pink); }

/* right green card: answer text + a tilted screenshot placeholder popping out the top */
.detail-stack { position: relative; flex: 1 1 auto; min-height: 0; }
.detail-card { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(16px, 2.6vh, 28px);
  opacity: 0; transform: translateY(16px); transition: opacity .5s ease, transform .55s var(--ease-bounce); }
.detail-card.active { opacity: 1; transform: none; }
/* framed "photo": white matte + black outline + hard offset shadow, tilted */
.dc-shot { flex: none; width: min(80%, 440px); margin: 0 auto;
  padding: 9px; background: #fff; border: 1.5px solid #0f0f0f; border-radius: 8px;
  box-shadow: 8px 8px 0 0 rgba(0,0,0,0.85); transform: rotate(3deg); }
.dc-img { display: block; width: 100%; aspect-ratio: 16 / 10; border-radius: 3px;
  background: #e7e7e5 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23b7b7b1' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='16' rx='2'/><circle cx='8.5' cy='9' r='1.5'/><path d='M4 18l5-5 4 4 3-3 4 4'/></svg>") center / 50px no-repeat; }
.dc-body { flex: none; display: flex; align-items: center; justify-content: center; padding: 0 clamp(18px, 2.6vw, 36px); }
.detail-text { font-size: clamp(17px, 1.7vw, 26px); font-weight: 800; line-height: var(--lh-tight); letter-spacing: var(--trk-tight); color: #0a0a0a; text-align: center; max-width: 24ch; }

/* closing line sits at the bottom of the "stuck doing" card, below the list */
.grind-close { flex: none; margin-top: clamp(12px, 1.8vh, 20px); text-align: center;
  font-size: clamp(12px, 0.95vw, 15px); font-weight: 700; line-height: 1.4; color: var(--ink); }
.grind-close em { font-style: italic; }

/* ---------- Intro choreography ----------
   The lead text SPRINGS in with a scale bounce (ease-bounce overshoots its rest),
   staggered by the .d-* delays; the headline gets the biggest pop. */
.anim { opacity: 0; transform: translateY(-8px) scale(1.06); }
body.go .anim { opacity: 1; transform: none; transition: opacity .6s ease, transform .85s var(--ease-bounce); }
/* the hero headline drops in BIG and settles down — the star of the bounce */
.lead .headline.anim { transform: translateY(-6px) scale(1.2); }
body.go .lead .headline.anim { transform: none; transition: opacity .55s ease, transform .95s var(--ease-bounce); }
body.go .window { top: 85vh; transition: top 1.05s var(--ease-bounce) .7s; }
.d-head { transition-delay: .3s !important; }
.d-over { transition-delay: .6s !important; }
.d-desc { transition-delay: .85s !important; }
.d-act  { transition-delay: 1.05s !important; }
.d-hint { transition-delay: 1.95s !important; }

/* Lead title sequence, matching the in-window one: the headline words land, THEN
   the green highlight WIPES in behind them (left-to-right), THEN the sticker.
   We override the base solid green with a 0%-wide gradient so the sweep reads;
   the highlight text stays dark, so it's legible on both the ground and green. */
.lead .headline .hl { background-color: transparent;
  background-image: linear-gradient(var(--green), var(--green));
  background-repeat: no-repeat; background-position: left center; background-size: 0% 100%; }
body.go .lead .headline .hl { background-size: 100% 100%;
  transition: background-size .55s cubic-bezier(0.22, 1, 0.36, 1) 1.25s; }
.hl-sticker { opacity: 0; }
body.go .hl-sticker { animation: hl-sticker-pop .6s var(--ease-bounce) 1.7s both; }
/* No translateY(-50%) any more: the sticker used to be absolutely placed at
   top:50% and the keyframes had to undo that on every step. It sits in flow at
   the end of the last word now (so a wrapped highlight can't strand it between
   the lines), and carrying the old offset here would have thrown it half its
   height up the moment the animation took over from the static rule. */
@keyframes hl-sticker-pop {
  0%   { opacity: 0; transform: rotate(-24deg) scale(0.2); }
  55%  { opacity: 1; transform: rotate(13deg)  scale(1.12); }
  100% { opacity: 1; transform: rotate(8deg)   scale(1); }
}

@media (max-width: 900px) { .window { width: 92vw; } }

/* ---------- Reduced motion: window + app view stack statically ----------
   (each variant additionally handles its own lead/ground fallbacks) */


/* ---------- custom 3 Sided Cube cursor (fine pointer only) ---------- */
@media (pointer: fine) {
  html.has-cursor, html.has-cursor * { cursor: none !important; }
}
.cursor { position: fixed; top: 0; left: 0; width: 32px; height: 32px; z-index: 99999; pointer-events: none;
  transform: translate(-100px, -100px); will-change: transform; }
.cursor img { position: absolute; top: -3px; left: -4px; width: 32px; height: 32px; display: block; user-select: none; -webkit-user-drag: none; }
.cursor .cur-hand { display: none; }
.cursor.hover .cur-arrow { display: none; }
.cursor.hover .cur-hand { display: block; }
.cursor.down { }

