/* ------------------------------------------------------------------------
   CHROME. The app's own window frame, and everything built out of it.

   public/art/ui/window.png is a 13x13 nine-slice with 6px corners. Read out
   of the file, it is a two pixel line: #090a14 on the outside, #a4dddb on the
   inside, with the four corner pixels cut away. Its centre is transparent on
   purpose, because the app paints a gradient behind it. So do we, with the
   two colours named in art/ui/chrome.json.

   This is the single thing that makes the page feel like the app instead of
   like a website about the app. Use it for panels, cards and buttons, and do
   not invent a second kind of box.
   ------------------------------------------------------------------------ */

.frame{
  border-style:solid;
  border-width:var(--frame-w);
  /* 6px slice drawn at 12px (2x) or 18px (3x). Whole numbers, both. */
  border-image:url('/art/ui/window.png') 6 / var(--frame-w) / 0 stretch;
  background:linear-gradient(180deg,var(--depth-far),var(--depth-near));
  image-rendering:pixelated;
}

.frame--pressed,
.frame[data-pressed]{
  border-image-source:url('/art/ui/window_pressed.png');
  background:linear-gradient(180deg,var(--panel),var(--depth-far));
}

/* A frame with nothing painted behind it, for wrapping art that fills it. */
.frame--bare{background:var(--void)}

/* --- buttons -------------------------------------------------------------
   The same frame, an accent fill behind it, a hard bottom edge, and a 4px
   press that takes the edge away. No transition on the press: it should feel
   like a key going down, not like a web page.
   ------------------------------------------------------------------------ */
.btn{
  display:inline-block;
  cursor:pointer;
  text-decoration:none;
  text-align:center;
  font-family:var(--face-pixel);
  font-smooth:never;
  -webkit-font-smoothing:none;
  font-size:var(--f-ui);
  line-height:var(--lh-ui);
  color:var(--void);
  padding:var(--sp-3) var(--sp-5);
  border-style:solid;
  border-width:var(--frame-w);
  border-image:url('/art/ui/window.png') 6 / var(--frame-w) / 0 stretch;
  background:linear-gradient(180deg,var(--accent),var(--accent-shade));
  box-shadow:0 4px 0 0 var(--depth-far);
}

.btn:hover{background:linear-gradient(180deg,var(--accent-shade),var(--accent-shade))}

.btn:active{
  transform:translateY(4px);
  box-shadow:none;
  border-image-source:url('/art/ui/window_pressed.png');
}

/* While the waitlist request is in flight. The gold goes out of it and the
   hard edge goes with it, so it reads as held down rather than as faded.
   Both colours are Apollo: no opacity, which would make a colour that is not. */
.btn[disabled]{
  cursor:default;
  color:var(--ink-muted);
  background:linear-gradient(180deg,var(--border-active),var(--border-quiet));
  box-shadow:none;
  transform:translateY(4px);
  border-image-source:url('/art/ui/window_pressed.png');
}

.btn--quiet{
  color:var(--ink-bright);
  background:linear-gradient(180deg,var(--depth-far),var(--depth-near));
}

/* --- cards ---------------------------------------------------------------- */
.cards{
  display:grid;
  gap:var(--sp-6);
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
}

.card{padding:var(--sp-5)}
.card .h3{margin-bottom:var(--sp-3)}

/* --- the form -------------------------------------------------------------
   THREE ELEMENTS AND NOTHING ELSE: a label, a field, a button. The nine-slice
   frame is on the panel around it (.pact-panel), not on the form, because a
   framed form inside a framed panel is a box in a box.
   ------------------------------------------------------------------------ */
.pact-form{
  display:grid;
  gap:var(--sp-4);
  max-width:420px;
}

/* A grid item stretches by default, and a button the full width of the panel
   reads as a bar rather than as a key to press. */
.pact-form .btn{justify-self:start}

.ui-label{
  display:block;
  font-family:var(--face-pixel);
  font-smooth:never;
  -webkit-font-smoothing:none;
  font-size:var(--f-ui);
  line-height:var(--lh-ui);
  color:var(--ink-bright);
}

.field{
  width:100%;
  font-family:var(--face-body);
  font-size:var(--f-body);
  line-height:1.4;
  padding:var(--sp-3) var(--sp-4);
  color:var(--ink-bright);
  background:var(--panel);
  border:2px solid var(--border-active);
  border-radius:0;
}
.field::placeholder{color:var(--ink-muted)}
/* Clicking into the field turns its border gold and that is enough. Arriving
   on it with the Tab key gets the page's own focus ring as well, because a
   border colour change is a weak thing to hunt for with a keyboard. */
.field:focus{outline:0;border-color:var(--accent)}
.field:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
.field[aria-invalid="true"]{border-color:var(--danger-hot)}

.msg{
  margin-top:var(--sp-4);
  min-height:var(--lh-kicker);
  font-size:var(--f-small);
  line-height:var(--lh-small);
  color:var(--ink-muted);
}
.msg.is-bad{color:var(--danger-hot)}

/* --- the success stamp ---------------------------------------------------
   The reward. Green appears exactly once on this page and this is it.

   IT IS A STAMP, so it comes down from above and it lands: a clip that opens
   downward and a 12px drop, both in four hard steps over a third of a second.
   No fade and no scale. A pixel heading at a fractional size or a fractional
   opacity is a colour that is not in the palette, and the whole page is built
   to avoid exactly that.

   The 3D behind it moves on the same beat: js/stage/pact.js flares the fire
   back up and brings the party round. See js/waitlist.js for the one event
   that ties the two together.
   ------------------------------------------------------------------------ */
.stamp{
  max-width:420px;
  padding:var(--sp-5);
  background:linear-gradient(180deg,var(--depth-far),var(--depth-near));
  box-shadow:inset 0 0 0 2px var(--success);
}
.stamp .kicker{color:var(--success)}
.stamp .h3{color:var(--success-bright);margin-top:var(--sp-2)}
.stamp p{color:var(--ink)}

/* The address that was actually signed, on its own line, like a name written
   at the bottom of a page. Pixel face at 22px, which is a whole multiple of
   LanaPixel's 11. A long address wraps rather than running off a phone. */
.signature{
  margin-top:var(--sp-4);
  padding-bottom:var(--sp-2);
  font-size:var(--f-ui);
  line-height:var(--lh-ui);
  color:var(--accent);
  overflow-wrap:anywhere;
  border-bottom:2px solid var(--accent-shade);
}
.stamp .signature + p{margin-top:var(--sp-4)}

/* Only when motion is allowed. With reduced motion, or with no JavaScript at
   all, the stamp is simply there. */
html.anim .stamp.is-new{animation:stamp-in .32s steps(4,end) 1}

@keyframes stamp-in{
  from{clip-path:inset(100% 0 0 0);transform:translateY(-12px)}
  to  {clip-path:inset(0 0 0 0);transform:translateY(0)}
}

/* --- a two frame idle cycle, in CSS ---------------------------------------
   The sprite folders hold idle_0 and idle_1. The app plays them at about two
   frames a second, so the site does too. visibility, not opacity: a half
   faded pixel sprite would be a colour that is not in the palette.
   ------------------------------------------------------------------------ */
.idle{position:relative;display:block}
.idle img + img{position:absolute;inset:0;visibility:hidden}
