/* ==========================================================================
   Kaico Studio — shared base.
   Design tokens, the reset, the animation vocabulary, and the handful of
   layout primitives that every page uses. Page-specific rules live in
   /assets/<page>.css, which loads after this file and wins on conflict.
   ========================================================================== */

:root {
  /* Palette */
  --ink:    #14100c;
  --cream:  #f4ead6;
  --red:    oklch(0.72 0.19 29);
  --yellow: oklch(0.85 0.19 98);
  --cyan:   oklch(0.78 0.14 200);

  /* Type */
  --display: 'Rubik Mono One', 'Arial Black', sans-serif;
  --pixel:   'Pixelify Sans', ui-monospace, Menlo, monospace;
  --mono:    'DM Mono', ui-monospace, Menlo, monospace;
}

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */

/* NB: no global box-sizing reset. The canvas pages are authored against the
   default content-box, and switching them to border-box silently narrows
   every padded container (it costs the games grid a whole column). The
   homepage opts in for itself in home.css. */

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

html, body {
  margin: 0;
  /* Tilted cards with hard offset shadows push past the viewport edge. */
  overflow-x: hidden;
}

body {
  background: var(--cream);
  font-family: var(--mono);
}

a { color: var(--ink); text-decoration: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: inherit;
}

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

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */

/* A band of page content. Every major section on a subpage is one of these. */
.section {
  padding:52px 20px 0;
  max-width:1240px;
  margin:0 auto;
}

/* The tilted heading chip plus its note, side by side until they cannot be. */
.section-head {
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:14px;
}

/* Right-hand cluster in the sticky bar (sound toggle, status badge). */
.sitebar-tools {
  pointer-events:auto;
  display:flex;
  gap:8px;
  align-items:flex-start;
}

.footer-row {
  max-width:1240px;
  margin:0 auto;
  display:flex;
  flex-wrap:wrap;
  gap:20px;
  justify-content:space-between;
  align-items:center;
}

.chip-row {
  display:flex;
  flex-wrap:wrap;
  gap:10px;
}

.card-grid {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr));
  gap:24px;
  align-items:start;
}

.card-head {
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:10px;
  margin:0 0 12px;
}

.nowrap {
  white-space:nowrap;
}


/* --------------------------------------------------------------------------
   Cursor trail — glyphs dropped behind the pointer, then faded out.
   site.js reads the glyph set and colours from data- attributes on <body>.
   -------------------------------------------------------------------------- */

.cursor-trail {
  position: fixed;
  left: 0;
  top: 0;
  pointer-events: none;
  font: 400 15px/1 var(--pixel);
  animation: kfade .75s linear forwards;
  z-index: 9999;
}

/* --------------------------------------------------------------------------
   Animation vocabulary. Names are the canvas originals so the generated
   page CSS keeps referring to them:
     kmarq/kmarqr  marquee scroll (and its reverse)
     kwig          wiggle        kjit   jitter
     kblink        blink         kfade  trail fade-out
     kspin/kspinr  rotation      kring  pulse ring
     kfill         progress fill kstar  twinkle
     khue          hue shift     kpulse scale pulse
   kbob, kglow and kscan are timed differently per page and live there.
   -------------------------------------------------------------------------- */

@keyframes kblink {0%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes kfade {from{opacity:.9;transform:translate(-50%,-50%) scale(1) rotate(0)}to{opacity:0;transform:translate(-50%,-50%) scale(.3) rotate(140deg)}}
@keyframes kfill {from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes khue {0%,100%{background-position:0 0}50%{background-position:60px 0}}
@keyframes kjit {0%,100%{transform:translate(0,0)}25%{transform:translate(1px,-1px)}50%{transform:translate(-1px,1px)}75%{transform:translate(1px,1px)}}
@keyframes kmarq {from{transform:translateX(0)}to{transform:translateX(-50%)}}
@keyframes kmarqr {from{transform:translateX(-50%)}to{transform:translateX(0)}}
@keyframes kpulse {0%,100%{transform:scale(1)}50%{transform:scale(1.06)}}
@keyframes kring {0%{transform:scale(.55);opacity:.85}100%{transform:scale(1.35);opacity:0}}
@keyframes kspin {from{transform:rotate(0)}to{transform:rotate(360deg)}}
@keyframes kspinr {from{transform:rotate(360deg)}to{transform:rotate(0)}}
@keyframes kstar {from{background-position:0 0}to{background-position:-1200px 0}}
@keyframes kwig {0%,100%{transform:rotate(-2.5deg)}50%{transform:rotate(2.5deg)}}


/* --------------------------------------------------------------------------
   Preview notice — the dismissible bar that hovers at the bottom of every
   page. Hidden for good once dismissed (site.js remembers in localStorage).
   -------------------------------------------------------------------------- */

.preview-note {
  position: fixed;
  z-index: 9998;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%) rotate(-0.6deg);
  display: flex;
  align-items: center;
  gap: 14px;
  width: min(760px, calc(100vw - 24px));
  padding: 12px 14px;
  background: var(--cream);
  border: 4px solid var(--ink);
  box-shadow: 7px 7px 0 var(--red);
  animation: knote .32s ease-out both;
}

.preview-note[hidden] { display: none !important; }

.preview-note-chip {
  flex: none;
  align-self: flex-start;
  padding: 6px 9px;
  background: var(--yellow);
  border: 2px solid var(--ink);
  font: 400 11px/1 var(--pixel);
  color: var(--ink);
  white-space: nowrap;
}

.preview-note-text {
  flex: 1;
  margin: 0;
  font: 500 11.5px/1.55 var(--mono);
  color: rgba(20,16,12,.85);
  text-wrap: pretty;
}

.preview-note-close {
  flex: none;
  align-self: flex-start;
  width: 30px;
  height: 30px;
  background: var(--ink);
  border: 2px solid var(--ink);
  font: 400 13px/1 var(--pixel);
  color: var(--cream);
}

.preview-note-close:hover {
  background: var(--red);
  color: var(--ink);
}

@keyframes knote {
  from { opacity: 0; transform: translateX(-50%) rotate(-0.6deg) translateY(14px); }
  to   { opacity: 1; transform: translateX(-50%) rotate(-0.6deg) translateY(0); }
}

@media (max-width: 560px) {
  .preview-note {
    left: 12px;
    right: 12px;
    width: auto;
    bottom: 12px;
    gap: 10px;
    flex-wrap: wrap;
    transform: rotate(-0.6deg);
    box-shadow: 5px 5px 0 var(--red);
  }
  .preview-note-text { flex: 1 1 100%; order: 3; }
  @keyframes knote {
    from { opacity: 0; transform: rotate(-0.6deg) translateY(14px); }
    to   { opacity: 1; transform: rotate(-0.6deg) translateY(0); }
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — the crooked layout stays, the movement stops.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .cursor-trail { display: none; }
}
