/* The Cube — public controller for the 8x8x8. Same deep field, teal and gold
   as EPI Pad (play-app/style.css); this page is a sibling of that one, not a
   new look. Unlike the pad, this page DOES scroll: it is a list of controls,
   not a gamepad, so touch-action stays normal and the body is not locked. */

:root{
  --bg:#070a0f;
  --bg2:#0b111a;
  --ink:#dfe9ee;
  --dim:#6d8494;
  --teal:#3fd7c4;
  --teal-dk:#1b6f68;
  --gold:#e8b24a;
  --gold-dk:#7a5c1f;
  --line:rgba(63,215,196,.20);
  --bad:#ff5964;
  --ease:cubic-bezier(.2,.8,.2,1);
}

*{box-sizing:border-box;margin:0;padding:0}

html{
  /* every width below 360px still fits without a sideways drag */
  -webkit-text-size-adjust:100%;
}

body{
  min-height:100%;
  background:var(--bg);
  color:var(--ink);
  font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  overflow-x:hidden;              /* belt: nothing may ever scroll sideways */
  -webkit-tap-highlight-color:transparent;
  padding:env(safe-area-inset-top) env(safe-area-inset-right)
          env(safe-area-inset-bottom) env(safe-area-inset-left);
}

#bg{
  position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(1200px 700px at 20% -10%, rgba(63,215,196,.10), transparent 60%),
    radial-gradient(900px 600px at 110% 110%, rgba(232,178,74,.08), transparent 60%),
    linear-gradient(180deg,var(--bg) 0%, var(--bg2) 55%, var(--bg) 100%);
  background-attachment:fixed;
}

/* ---------------------------------------------------------------- top bar */

#topbar{
  position:sticky; top:0; z-index:3;
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:12px 14px 10px;
  font-size:12px; letter-spacing:.16em;
  background:linear-gradient(180deg,rgba(7,10,15,.94),rgba(7,10,15,.72) 70%,transparent);
  backdrop-filter:blur(6px);
}
#brand{color:var(--dim); font-weight:700}
#brand span{color:var(--teal)}

#conn{display:flex; align-items:center; gap:7px; font-size:10.5px; letter-spacing:.12em; color:var(--dim)}
#conn-dot{
  width:7px; height:7px; border-radius:50%; flex:0 0 auto;
  background:var(--dim); box-shadow:0 0 0 3px rgba(109,132,148,.14);
  transition:background .25s var(--ease), box-shadow .25s var(--ease);
}
#conn.ok  #conn-dot{background:var(--teal); box-shadow:0 0 0 3px rgba(63,215,196,.16)}
#conn.bad #conn-dot{background:var(--bad);  box-shadow:0 0 0 3px rgba(255,89,100,.16)}
#conn.busy #conn-dot{background:var(--gold);box-shadow:0 0 0 3px rgba(232,178,74,.18)}

/* ------------------------------------------------------------------ shell */

main{
  position:relative; z-index:1;
  max-width:560px; margin:0 auto;
  padding:4px 14px 34px;
  display:flex; flex-direction:column; gap:14px;
}

.card{
  background:rgba(11,17,26,.66);
  border:1px solid rgba(255,255,255,.06);
  border-radius:16px;
  padding:16px 14px;
}

.card-head{display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:13px}
.card-head h2{font-size:13px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--ink)}
.hint{font-size:10.5px; letter-spacing:.12em; color:var(--dim)}

.lede{font-size:12.5px; line-height:1.7; color:var(--dim); margin-bottom:13px}

/* ---------------------------------------------------------------- effects */

.grid{
  display:grid;
  /* two up on a phone, and at 320px each tile is still ~137px wide */
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:10px;
  transition:opacity .3s var(--ease);
}

.fx{
  position:relative;
  display:flex; flex-direction:column; justify-content:flex-end;
  gap:2px;
  min-height:82px;                 /* a thumb-sized target, not a link */
  padding:12px 12px 11px;
  border:1px solid rgba(255,255,255,.08);
  border-radius:13px;
  background:var(--g,#111);
  color:#fff;
  font:inherit; text-align:left;
  cursor:pointer;
  overflow:hidden;
  touch-action:manipulation;
  transition:transform .16s var(--ease), box-shadow .22s var(--ease), border-color .22s var(--ease);
}
/* the gradient is the mood; this scrim is what keeps the label readable on it */
.fx::before{
  content:""; position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.05),rgba(0,0,0,.55));
  pointer-events:none;
}
.fx > *{position:relative}
.fx .n{font-size:13.5px; font-weight:700; letter-spacing:.02em}
.fx .m{font-size:10.5px; letter-spacing:.1em; color:rgba(255,255,255,.66)}
.fx:active{transform:scale(.975)}

.fx .tick{
  position:absolute; top:9px; right:10px;
  font-size:12px; line-height:1;
  opacity:0; transform:scale(.7);
  transition:opacity .2s var(--ease), transform .2s var(--ease);
}
.fx[aria-pressed="true"]{
  border-color:rgba(255,255,255,.5);
  box-shadow:0 0 0 1px rgba(255,255,255,.28), 0 8px 26px -8px var(--glow,rgba(63,215,196,.5));
}
.fx[aria-pressed="true"] .tick{opacity:1; transform:scale(1)}

.fx.wide{
  /* a <button> resolves width:auto to fit-content even at display:flex, so
     without this the test button sits at ~60% and looks like a mistake */
  width:100%;
  margin-top:10px;
  min-height:60px;
  /* .fx sets justify-content:flex-end to push the label to the bottom of a
     tall column tile; once this one turns into a ROW that same rule shoves the
     text to the right edge, so it has to be reset here */
  flex-direction:row; align-items:center; justify-content:flex-start; gap:9px;
  background:none;
  border:1px dashed rgba(232,178,74,.3);
  --glow:rgba(232,178,74,.45);
}
.fx.wide::before{display:none}
.fx.wide .n{color:var(--gold)}
.fx.wide .m{color:var(--dim)}
.fx.wide[aria-pressed="true"]{border-style:solid; border-color:rgba(232,178,74,.7)}

/* Locked out: a game holds the claim, or the cube is not answering. The tiles
   stay visible (so you can see what the cube IS doing) but refuse taps, because
   firing an effect at a claimed cube just earns a 409. */
#fx-card.locked .grid,
#fx-card.locked #fx-selftest{opacity:.35; pointer-events:none; filter:saturate(.5)}

.note{
  margin-top:12px;
  font-size:12px; line-height:1.65; color:var(--dim);
  display:flex; align-items:flex-start; gap:8px;
}
.note[hidden]{display:none}
.note::before{
  content:""; flex:0 0 auto; margin-top:6px;
  width:7px; height:7px; border-radius:50%;
  background:var(--dim); box-shadow:0 0 0 3px rgba(109,132,148,.12);
}
.note.bad::before{background:var(--bad); box-shadow:0 0 0 3px rgba(255,89,100,.14)}
.note.busy::before{background:var(--gold); box-shadow:0 0 0 3px rgba(232,178,74,.16)}
.note.busy{color:#d4bb85}
.note.quiet{font-size:11.5px; opacity:.82}
.note.ok::before{background:var(--teal); box-shadow:0 0 0 3px rgba(63,215,196,.16)}

/* ------------------------------------------------------------------ snake */

.card.play{
  display:flex; align-items:center; gap:13px;
  text-decoration:none; color:inherit;
  border-color:rgba(63,215,196,.22);
  background:linear-gradient(135deg,rgba(63,215,196,.10),rgba(11,17,26,.7) 62%);
  transition:transform .16s var(--ease), border-color .22s var(--ease);
  touch-action:manipulation;
}
.card.play:active{transform:scale(.99); border-color:rgba(63,215,196,.45)}
.play-ico{flex:0 0 auto; width:30px; height:30px; color:var(--teal)}
.play-ico svg{width:100%; height:100%; display:block}
.play-txt{flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:3px}
.play-txt strong{font-size:13.5px; letter-spacing:.03em}
.play-txt span{font-size:11.5px; color:var(--dim); line-height:1.5}
.play-arrow{flex:0 0 auto; color:var(--teal); font-size:16px}

/* ------------------------------------------------------------ suggestions */

#sg-text{
  width:100%;
  background:rgba(7,10,15,.7);
  border:1px solid rgba(255,255,255,.09);
  border-radius:11px;
  color:var(--ink);
  font:inherit; font-size:13px; line-height:1.6;
  padding:11px 12px;
  resize:vertical;
  min-height:78px;
}
#sg-text:focus{outline:none; border-color:rgba(63,215,196,.45); box-shadow:0 0 0 3px rgba(63,215,196,.09)}
#sg-text::placeholder{color:#4d6473}

.sg-row{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:10px}
.count{font-size:11px; color:var(--dim); letter-spacing:.08em}
.count.low{color:var(--gold)}

.send{
  flex:0 0 auto;
  padding:11px 16px;
  min-height:44px;
  border:1px solid rgba(63,215,196,.35);
  border-radius:11px;
  background:rgba(63,215,196,.12);
  color:var(--teal);
  font:inherit; font-size:12px; font-weight:700; letter-spacing:.1em;
  cursor:pointer;
  touch-action:manipulation;
  transition:transform .16s var(--ease), opacity .2s var(--ease);
}
.send:active{transform:scale(.97)}
.send[disabled]{opacity:.45; cursor:default}

footer{
  text-align:center;
  font-size:10.5px; letter-spacing:.14em; color:#3d5261;
  padding:6px 0 2px;
}

/* ------------------------------------------------------------------ toast */

#toast{
  position:fixed; left:50%; bottom:calc(20px + env(safe-area-inset-bottom));
  transform:translateX(-50%);
  z-index:9;
  max-width:min(90vw,420px);
  padding:11px 16px;
  border:1px solid rgba(255,255,255,.1);
  border-radius:11px;
  background:rgba(11,17,26,.96);
  color:var(--ink);
  font-size:12px; line-height:1.5; text-align:center;
  box-shadow:0 12px 40px -12px rgba(0,0,0,.9);
  transition:opacity .22s var(--ease), transform .22s var(--ease);
}
#toast.hidden{opacity:0; transform:translate(-50%,8px); pointer-events:none}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important; animation:none !important}
}
