:root {
  --void: #050403;
  --gold: #d7b56a;
  --cream: #f4ead6;
  --mute: #a39680;
  --mast: 62px;
  --host: 68px;

  /* One display face per category. Games get a hard condensed poster face,
     AI/platforms a technical one, tools a clean geometric — so the wall reads
     as three different kinds of product rather than one template. */
  --face-games: "Bebas Neue", Impact, "Haettenschweiler", sans-serif;
  --face-ai: "Chakra Petch", "Segoe UI", sans-serif;
  --face-tools: "Space Grotesk", "Segoe UI", sans-serif;
  --face-brand: "Cinzel", Georgia, serif;
}
* { box-sizing: border-box; }
html, body {
  margin: 0;
  /* dvh, not vh: on phones vh is the *largest* viewport, so with the browser
     bars showing the bottom of the page sits under them and the host bar gets
     clipped. dvh tracks the actual visible height. */
  height: 100dvh;
  overflow: hidden;
  background: var(--void);
  color: var(--cream);
  font-family: "Segoe UI", Georgia, serif;
  -webkit-text-size-adjust: 100%;
}
button, input, a { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; }
[hidden] { display: none !important; }

/* --- entry gate ---------------------------------------------------------- */

.gate {
  position: fixed; inset: 0; z-index: 60;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 26px;
  background:
    radial-gradient(120% 90% at 50% 40%, rgba(215,181,106,.10), transparent 60%),
    var(--void);
  transition: opacity .6s ease;
}
.gate.out { opacity: 0; pointer-events: none; }
.gate-brand {
  margin: 0;
  color: var(--gold);
  letter-spacing: .5em;
  text-indent: .5em;
  font-size: clamp(20px, 5vw, 38px);
  animation: gateIn .9s ease both;
}
#gateEnter {
  border: 1px solid rgba(215,181,106,.5);
  color: var(--gold);
  letter-spacing: .3em;
  text-indent: .3em;
  text-transform: uppercase;
  font-size: 13px;
  padding: 16px 44px;
  transition: background .3s ease, border-color .3s ease;
  animation: gateIn .9s ease .25s both;
}
#gateEnter:hover { background: rgba(215,181,106,.12); border-color: var(--gold); }
.gate-hint {
  margin: 0;
  color: var(--mute);
  letter-spacing: .22em;
  text-transform: uppercase;
  font-size: 10px;
  animation: gateIn .9s ease .5s both;
}
@keyframes gateIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; } }

#intro {
  position: fixed; inset: 0; z-index: 40;
  width: 100%; height: 100%;
  object-fit: cover;
  background: #000;
}
#intro.out {
  opacity: 0;
  transition: opacity .9s ease;
  pointer-events: none;
}

#introSkip {
  position: fixed; z-index: 41;
  right: 18px; bottom: calc(18px + env(safe-area-inset-bottom));
  color: var(--gold);
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: 11px;
  border: 1px solid rgba(215,181,106,.4);
  background: rgba(5,4,3,.55);
  padding: 10px 16px;
  opacity: 0;
  animation: skipIn .5s ease 1.6s forwards;
}
#introSkip:hover { background: rgba(5,4,3,.8); border-color: var(--gold); }
@keyframes skipIn { to { opacity: .75; } }

/* --- chrome -------------------------------------------------------------- */

.mast {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  height: var(--mast);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 18px;
  background: linear-gradient(rgba(5,4,3,.82), transparent);
}
.brand {
  font-family: var(--face-brand);
  color: var(--gold);
  letter-spacing: .3em;
  text-indent: .3em;
  text-transform: uppercase;
  font-size: clamp(17px, 1.5vw, 22px);
}
.mast nav { display: flex; gap: 2px; }
/* Was 11px and near-invisible against the gradient. */
.mast nav button {
  position: relative;
  color: var(--cream);
  opacity: .72;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-size: clamp(13px, 1.05vw, 16px);
  font-weight: 600;
  padding: 10px 16px;
  transition: opacity .25s ease, color .25s ease;
}
.mast nav button::after {
  content: "";
  position: absolute; left: 16px; right: 16px; bottom: 4px;
  height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transition: transform .3s cubic-bezier(.2,.8,.2,1);
}
.mast nav button:hover, .mast nav button.on { color: var(--gold); opacity: 1; }
.mast nav button:hover::after, .mast nav button.on::after { transform: scaleX(1); }

.stage { position: fixed; inset: 0; z-index: 5; }

/* --- wall ---------------------------------------------------------------- */

.wall {
  position: absolute;
  inset: 0;
  display: grid;
  /* --cols is set from JS to track how many tiles the current filter shows. */
  grid-template-columns: repeat(var(--cols, 8), 1fr);
  grid-auto-rows: 1fr;
  gap: 5px;
  padding: 5px;
  padding-top: var(--mast);
  padding-bottom: calc(var(--host) + env(safe-area-inset-bottom));
}
.tile {
  position: relative;
  padding: 0;
  background: none;
  perspective: 1100px;
  /* Grid items default to min-height:auto, which lets a row grow past its 1fr
     share and pushes the bottom row under the host bar. */
  min-height: 0;
  min-width: 0;
  /* The entrance fades only — deliberately no transform on the grid item.
     A translate here rides on top of the item's grid position, so any moment
     the animation isn't at its end frame the tile sits below its track and the
     bottom row slides under the host bar. Opacity can't move anything, so the
     layout is correct at every frame regardless of animation state. */
  opacity: 1;
  transform: none;
  animation: bloom .55s ease backwards;
}
/* The card that actually turns. Two faces, so a flip reveals what the project
   does rather than just spinning for the sake of it. */
.tile-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .85s cubic-bezier(.4,.15,.2,1);
}
.tile.flip .tile-inner, .tile:focus-visible .tile-inner { transform: rotateY(180deg); }
.tile-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.tile-back {
  transform: rotateY(180deg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .5em;
  padding: 8% 9%;
  text-align: left;
  background:
    radial-gradient(120% 80% at 20% 0%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%),
    #0b0908;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.tile-back-name {
  font-family: var(--face);
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: clamp(13px, 1.35vw, 24px);
  line-height: 1;
}
.tile-back-does {
  color: var(--cream);
  font-size: clamp(9px, .68vw, 13px);
  line-height: 1.45;
  opacity: .85;
}
.tile-back-status {
  color: var(--accent);
  opacity: .65;
  font-size: clamp(7px, .5vw, 10px);
  letter-spacing: .18em;
  text-transform: uppercase;
}

.tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .55s ease, filter .45s ease;
}
/* Titles are real text — the artwork has no words baked into it, so a tile can
   be cropped to any shape without losing its name, and the type can carry its
   own font and colour per project. */
.tile-name, .tile-blurb {
  position: absolute;
  left: 0; right: 0;
  text-align: center;
  pointer-events: none;
  transition: transform .45s ease, opacity .45s ease;
}
.tile-name {
  bottom: 1.6em;
  font-family: var(--face);
  color: var(--accent);
  letter-spacing: .05em;
  text-transform: uppercase;
  font-size: clamp(13px, 1.45vw, 26px);
  line-height: 1.05;
  padding: 0 .3em;
  text-shadow: 0 2px 16px rgba(0,0,0,.95), 0 0 6px rgba(0,0,0,.9);
}
.tile-blurb {
  bottom: .7em;
  color: var(--cream);
  font-size: clamp(8px, .62vw, 11px);
  letter-spacing: .04em;
  padding: 0 .5em;
  opacity: .68;
  text-shadow: 0 1px 10px rgba(0,0,0,.95);
}
/* Per-category display faces. */
.tile[data-cat="games"] { --face: var(--face-games); }
.tile[data-cat="ai"]    { --face: var(--face-ai); }
.tile[data-cat="tools"] { --face: var(--face-tools); }
/* Bebas is all-caps and sits tight; give the others room. */
.tile[data-cat="ai"] .tile-name,
.tile[data-cat="tools"] .tile-name { font-size: clamp(11px, 1.15vw, 20px); font-weight: 700; }

/* A scrim so the type holds up over a bright poster. */
.tile-front::before {
  content: "";
  position: absolute; inset: auto 0 0 0;
  height: 48%;
  background: linear-gradient(transparent, rgba(5,4,3,.92) 78%);
  pointer-events: none;
}
.tile-front::after {
  content: "";
  position: absolute; inset: 0;
  padding: 1px;
  background: conic-gradient(from var(--a, 0deg), transparent 0 70%, var(--accent) 78%, color-mix(in srgb, var(--accent) 40%, #000) 88%, transparent 94%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity .25s ease;
}
.tile:hover img, .tile.focus img { transform: scale(1.06); }
.tile:hover .tile-name, .tile.focus .tile-name { transform: translateY(-4px); }
.tile:hover .tile-front::after, .tile.focus .tile-front::after {
  opacity: 1;
  animation: travel 2.2s linear infinite;
}
/* A lift on hover, so the wall responds before anything is even clicked. */
.tile:hover .tile-inner { transform: translateZ(26px); }
.tile.flip:hover .tile-inner { transform: rotateY(180deg); }

.wall.dim .tile:not(.focus) img { filter: brightness(.45) saturate(.8); }
.wall.dim .tile:not(.focus) .tile-name,
.wall.dim .tile:not(.focus) .tile-blurb { opacity: .25; }
@keyframes bloom { from { opacity: 0; } }
@keyframes travel { to { --a: 360deg; } }
@property --a { syntax: "<angle>"; inherits: false; initial-value: 0deg; }

/* --- detail sheet -------------------------------------------------------- */

.sheet {
  position: absolute;
  inset: var(--mast) 0 calc(var(--host) + env(safe-area-inset-bottom)) 0;
  display: grid;
  grid-template-columns: minmax(280px, 42vw) 1fr;
  background: rgba(5,4,3,.72);
  backdrop-filter: blur(18px);
  z-index: 8;
}
.sheet img { width: 100%; height: 100%; object-fit: cover; }
.sheet-copy { padding: 36px 40px; overflow: auto; }
.sheet-close {
  position: absolute; top: 14px; right: 18px;
  color: var(--gold);
  letter-spacing: .12em;
  text-transform: uppercase;
  font-size: 11px;
  z-index: 2;
}
.sheet[data-cat="games"] { --face: var(--face-games); }
.sheet[data-cat="ai"]    { --face: var(--face-ai); }
.sheet[data-cat="tools"] { --face: var(--face-tools); }
.kicker { color: var(--accent, var(--gold)); letter-spacing: .22em; text-transform: uppercase; font-size: 12px; }
.sheet h1 {
  font-family: var(--face);
  font-weight: 700;
  color: var(--accent, var(--cream));
  letter-spacing: .03em;
  text-transform: uppercase;
  font-size: clamp(34px, 4.4vw, 58px);
  line-height: 1.02;
  margin: 10px 0 12px;
}
.status { color: var(--mute); letter-spacing: .16em; text-transform: uppercase; font-size: 11px; }
.sheet-actions button, .sheet-actions a { border-color: color-mix(in srgb, var(--accent, #d7b56a) 45%, transparent); color: var(--accent, var(--gold)); }
.sheet-actions button:hover, .sheet-actions a:hover { background: color-mix(in srgb, var(--accent, #d7b56a) 14%, transparent); }
.sheet-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; }
.sheet-note {
  margin: 0;
  color: var(--mute);
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: 11px;
  border: 1px dashed rgba(215,181,106,.3);
  padding: 12px 18px;
}
.sheet-actions button, .sheet-actions a {
  text-decoration: none;
  border: 1px solid rgba(215,181,106,.45);
  color: var(--gold);
  padding: 12px 18px;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: 11px;
}

/* --- viewer -------------------------------------------------------------- */

.viewer {
  position: absolute;
  inset: var(--mast) 0 calc(var(--host) + env(safe-area-inset-bottom)) 0;
  display: flex;
  flex-direction: column;
  z-index: 8;
  background: #080705;
}
.viewer-bar {
  display: flex; gap: 16px; align-items: center;
  padding: 8px 14px;
  color: var(--gold);
  letter-spacing: .12em;
  text-transform: uppercase;
  font-size: 11px;
}
.viewer-bar a { margin-left: auto; color: var(--mute); text-decoration: none; }
.viewer iframe { flex: 1; border: 0; width: 100%; background: #111; }
.viewer-block {
  flex: 1;
  display: grid; place-items: center;
  text-align: center;
  padding: 40px;
}

/* --- host bar ------------------------------------------------------------ */

/* Reads as a host talking to you, not a cookie notice. It gets its own lifted
   panel, a warm edge, a live indicator and a name — against a wall this dark, a
   flat strip of grey text at the bottom disappears into the furniture. */
.host {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 22;
  min-height: var(--host);
  display: grid;
  grid-template-columns: 52px 1fr minmax(180px, 26vw) auto;
  gap: 14px;
  align-items: center;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  /* Deep navy instead of near-black — separates the chat bar from the void
     background so it reads as its own panel, not a strip cut from the wall. */
  background:
    linear-gradient(to top, #0a1128 60%, rgba(10,17,40,.94));
  border-top: 1px solid rgba(215,181,106,.3);
  box-shadow: 0 -18px 44px rgba(0,0,0,.8), 0 -1px 0 rgba(215,181,106,.1) inset;
}
.host-avatar { position: relative; display: block; width: 48px; height: 48px; }
.host-avatar img {
  width: 48px; height: 48px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid rgba(215,181,106,.55);
  box-shadow: 0 0 0 3px rgba(215,181,106,.1), 0 0 22px rgba(215,181,106,.18);
}
/* Small "he's here" tell. */
.host-dot {
  position: absolute; right: 1px; bottom: 1px;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: #5fd28a;
  border: 2px solid #0a1128;
  animation: hostPulse 2.4s ease-in-out infinite;
}
@keyframes hostPulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

.host-copy { display: block; min-width: 0; }
.host-name {
  display: block;
  color: var(--gold);
  font-size: 10px;
  letter-spacing: .24em;
  text-transform: uppercase;
  margin-bottom: 3px;
}
.host-name em { font-style: normal; color: var(--mute); letter-spacing: .16em; }
.host p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--cream);
  /* Eli's intro is long by design; let it breathe but never take the screen. */
  max-height: 22vh;
  overflow-y: auto;
}
#hostForm { display: contents; }
#hostInput {
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(215,181,106,.3);
  border-radius: 999px;
  padding: 11px 16px;
  color: var(--cream);
  min-width: 0;
  transition: border-color .25s ease, background .25s ease;
}
#hostInput::placeholder { color: rgba(163,150,128,.75); }
#hostInput:focus {
  outline: none;
  border-color: var(--gold);
  background: rgba(255,255,255,.08);
}
.mic {
  position: relative;
  overflow: hidden;
  color: #0d0a08;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-size: 12px;
  border: 1px solid var(--gold);
  background: var(--gold);
  border-radius: 999px;
  padding: 12px 22px;
  transition: filter .2s ease, transform .2s ease;
}
.mic:hover { filter: brightness(1.12); transform: translateY(-1px); }
/* Level meter — fills from the bottom with the live mic peak, so it's obvious
   the page is actually hearing something rather than just claiming to. */
.mic::before {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: calc(var(--level, 0) * 100%);
  background: rgba(255,255,255,.35);
  transition: height .08s linear;
  pointer-events: none;
}
.mic.live {
  background: #c4514d;
  border-color: #e0776f;
  color: #fff;
  animation: micLive 1.4s ease-in-out infinite;
}
@keyframes micLive {
  0%,100% { box-shadow: 0 0 0 0 rgba(196,81,77,.55); }
  50%     { box-shadow: 0 0 0 9px rgba(196,81,77,0); }
}

/* --- microphone consent ------------------------------------------------- */

.mic-hint {
  position: absolute;
  right: 14px;
  bottom: calc(100% + 6px);
  color: var(--gold);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  background: rgba(5,4,3,.9);
  border: 1px solid rgba(215,181,106,.35);
  padding: 6px 10px;
  pointer-events: none;
  animation: hintPulse 2.6s ease-in-out infinite;
}
@keyframes hintPulse { 0%,100% { opacity: .55; } 50% { opacity: 1; } }

.mic-ask {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: center;
  padding: 24px;
  background: rgba(5,4,3,.82);
  backdrop-filter: blur(10px);
}
.mic-ask-card {
  max-width: 440px;
  border: 1px solid rgba(215,181,106,.35);
  background: #0b0908;
  padding: 30px 32px;
}
.mic-ask-card h2 {
  font-family: var(--face-brand);
  font-weight: 600;
  margin: 8px 0 14px;
  font-size: 26px;
}
.mic-ask-card p { margin: 0; color: var(--mute); line-height: 1.55; font-size: 14px; }
.mic-ask-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; }
.mic-ask-actions button {
  border: 1px solid rgba(215,181,106,.45);
  color: var(--gold);
  padding: 12px 18px;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-size: 11px;
}
#micAskYes { background: rgba(215,181,106,.14); }
#micAskYes:hover { background: rgba(215,181,106,.25); }
#micAskNo { color: var(--mute); border-color: rgba(163,150,128,.3); }

@media (max-width: 900px) {
  .sheet { grid-template-columns: 1fr; }
  .sheet img { max-height: 34vh; }
  .sheet-copy { padding: 22px 20px; }
  .host {
    position: fixed;
    grid-template-columns: 40px 1fr auto;
    gap: 10px;
    padding: 9px 11px calc(9px + env(safe-area-inset-bottom));
  }
  .mast nav button { padding: 10px 9px; letter-spacing: .1em; }
  .mic-ask-card { padding: 24px 20px; }
  .host-avatar, .host-avatar img { width: 40px; height: 40px; }
  .host p { font-size: 13px; line-height: 1.4; max-height: 20vh; }
  .host-name { font-size: 9px; letter-spacing: .2em; }
  .mic { padding: 11px 16px; font-size: 11px; }
  #hostForm, #hostInput { display: none; }
  .tile-blurb { display: none; }
  .tile-name { bottom: .55em; font-size: clamp(10px, 2.6vw, 15px); }
}

@media (prefers-reduced-motion: reduce) {
  .tile { animation: none; opacity: 1; transform: none; }
  .tile:hover::after, .tile.focus::after { animation: none; }
  .gate-brand, #gateEnter, .gate-hint { animation: none; }
}
