/* The play client's own layout. The colours, type and spacing tokens are the
   site's; only the arrangement is different, because a game screen is a stage
   with panels beside it rather than a column of prose. */

/* Every panel here is laid out with grid or flex, and a display rule beats the
   hidden attribute. Without this the sign-in dialog, the spawn card and both
   banners are on screen the whole time — which is how it read until it was
   looked at in a browser. */
[hidden] { display: none !important; }

/* Where the keyboard is (D-294). Every control on this screen used to fall back
   to whatever ring the browser draws, which on a dark stage is a thin blue line
   nobody can follow. One ring, in the site's own accent, two pixels clear of the
   thing it is on, and only for the keyboard: a mouse press does not draw it. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The page is the site's header, the stage, and the site's footer, and nothing
   scrolls: both bars are the same elements every other page has, so the game's
   chrome is not a second set that looks alike; the stage takes whatever height
   is left between them. The two dialogs are fixed and out of flow, so they take
   no row. */
body.play {
  height: 100vh;
  overflow: hidden;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
}

body.play main {
  margin: 0;
  padding: 0;
  max-width: none;
  min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr);
}

/* Only what the game adds to the site's bar: no wrapping, so the stage keeps
   its height, and the status has room between the brand and the places. */
.play-bar { flex-wrap: nowrap; gap: .8rem; padding-top: .45rem; padding-bottom: .45rem; }
.play-bar .status { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.play-bar .site-nav { flex-wrap: nowrap; }

.status { font-size: var(--type-ui); color: var(--ink-soft); }
.status.good { color: var(--accent); }
.status.bad { color: var(--danger-ink); }

.play-body {
  display: grid;
  grid-template-columns: 1fr 21rem;
  min-height: 0;
}

.stage {
  position: relative;
  min-height: 0;
  background: var(--stage-ground);
  overflow: hidden;
}

#view { display: block; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }

#labels { position: absolute; inset: 0; pointer-events: none; }

/* The label's strength is set per frame from app.js, because it depends on how
   far away the thing is and where the camera is — neither of which CSS knows.
   What is here is the anchor: a name hangs from the point over its subject and
   shrinks towards that point rather than towards its own middle, so a fading
   name stays over the thing it names. */
.world-label {
  position: absolute;
  transform: translate(-50%, -100%);
  transform-origin: 50% 100%;
  padding: .1rem .35rem;
  border-radius: var(--radius-control);
  font-size: var(--type-meta);
  font-weight: 620;
  white-space: nowrap;
  background: var(--stage-panel);
  backdrop-filter: blur(12px);
  color: var(--stage-ink);
  border: 1px solid var(--stage-line);
}

.world-label.me { background: var(--stage-accent); border-color: var(--good); }
.world-label.agent { background: color-mix(in srgb, var(--warn) 26%, var(--stage-panel)); border-color: var(--warn); }

/* Something showing a reading that nobody has named: a crate, a machine. It is
   a caption like any other and is thinned with them, only quieter. */
.world-label.shown { background: var(--stage-scrim); backdrop-filter: blur(8px); }

.label-name { display: block; }

/* What a thing is showing about itself, under its name and never louder than
   it: smaller, dimmer, and faded out by --readout-strength before the name
   itself goes. */
.label-readout {
  display: flex;
  align-items: center;
  gap: .25rem;
  margin-top: .1rem;
  font-size: var(--type-meta);
  font-weight: 400;
  color: var(--stage-ink-soft);
  opacity: var(--readout-strength, 1);
}

.readout-label { opacity: .72; }

.readout-track {
  display: inline-block;
  height: .3rem;
  border-radius: var(--radius-control);
  background: color-mix(in srgb, var(--stage-ink) 22%, transparent);
  overflow: hidden;
}

.readout-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--good);
}

#minimap {
  position: absolute;
  right: .7rem;
  bottom: .7rem;
  width: 11rem;
  height: 11rem;
  border-radius: var(--radius-surface);
  border: 1px solid var(--stage-line);
  /* No blur: the renderer paints this canvas opaque, so a backdrop filter
     here would be a snapshot nobody ever sees. */
  background: var(--stage-panel);
}

.overlay-line {
  padding: .35rem .6rem;
  border-radius: var(--radius-control);
  font-size: var(--type-ui);
  background: var(--stage-scrim);
  backdrop-filter: blur(8px);
  color: var(--stage-ink);
  max-width: min(36rem, 100%);
  margin: 0;
}

/* The bottom-left corner of the stage, as one column rather than three things
   each nailed to their own offset: the card for what you are looking at, and
   under it the line saying what to press. They move together, so neither can
   land on top of the other as one of them grows. The right margin keeps the
   column clear of the minimap. */
.stage-foot {
  position: absolute;
  left: .7rem;
  bottom: .7rem;
  right: 12.5rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .5rem;
  pointer-events: none;
}

.stage-foot > * { pointer-events: auto; }

/* ---- what is within arm's length (D-316) ------------------------------- */

/* A row of what you could use from where you are standing, over the card for
   whatever you are looking at. It wraps rather than scrolls: five short words
   fit a phone in two lines, and a row that scrolled sideways would hide the
   thing furthest away, which is the one you are walking towards. */
.reach-bar {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  max-width: min(30rem, 100%);
}

.reach-item {
  font: inherit;
  font-size: var(--type-ui);
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
  padding: .35rem .6rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: var(--shadow-raised);
  color: var(--ink);
  cursor: pointer;
}

.reach-item:hover { color: var(--accent); border-color: var(--accent); }
.reach-item .reach-verb { font-weight: 620; }
.reach-item .reach-what { color: var(--ink-soft); font-size: var(--type-meta); }

/* Out of the way while the world is asking something, exactly as the card is:
   the two want the same corner and the question is the more urgent. */
.stage.asking .reach-bar { display: none; }

/* ---- the thing you are looking at (D-286) ------------------------------ */

.focus-card {
  width: min(22rem, 100%);
  /* A thing with many verbs, or one whose forms are open, must not grow off the
     top of the stage: the card is anchored to the bottom and grows upwards, so
     it scrolls inside itself rather than taking the world with it. */
  max-height: 60vh;
  overflow-y: auto;
  padding: .6rem .7rem .7rem;
  border-radius: var(--radius-surface);
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-raised);
}

.focus-head { display: flex; align-items: baseline; gap: .5rem; }

.focus-card h2 {
  flex: 1;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: var(--type-lede);
  font-weight: 620;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.focus-close {
  font: inherit;
  font-size: var(--type-lede);
  line-height: 1;
  padding: .15rem .4rem;
  border: 0;
  border-radius: var(--radius-control);
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}

.focus-close:hover { color: var(--accent); background: var(--accent-soft); }

.focus-kind { margin: .1rem 0 .5rem; font-size: var(--type-meta); color: var(--ink-soft); }

/* A question and the card for the thing that asked it want the same corner of
   the stage, and a question is the more urgent of the two — it is usually
   *about* the thing you were looking at, and it is what the world is waiting
   on. So the card stands down while something is asking, and comes back with
   the same buttons the moment the question is answered. */
.stage.asking .focus-card { display: none; }

/* The verbs, as the buttons a person actually presses: bigger than a row
   action, because this is the control the whole screen is about. */
.focus-actions .verbs { gap: .4rem; margin-bottom: 0; }
.focus-actions .verb .row-action,
.focus-detailed .verb .row-action {
  font-size: var(--type-ui);
  padding: .4rem .7rem;
  margin-right: 0;
  color: var(--ink);
}

.focus-actions .verb .row-detail { font-size: var(--type-meta); }

.focus-more { margin-top: .5rem; }
.focus-more > summary { font-size: var(--type-ui); color: var(--ink-soft); cursor: pointer; }
.focus-more > summary:hover { color: var(--accent); }
.focus-more > div { margin-top: .45rem; }

.notice {
  position: absolute;
  left: 50%;
  top: 1rem;
  transform: translateX(-50%);
  padding: .5rem .8rem;
  border-radius: var(--radius-surface);
  font-size: var(--type-ui);
  max-width: min(40rem, 80%);
  background: var(--stage-panel);
  backdrop-filter: blur(12px);
  color: var(--stage-ink);
  border: 1px solid var(--stage-line);
  box-shadow: var(--shadow-raised);
}

.notice.bad { background: color-mix(in srgb, var(--danger) 38%, var(--stage-panel)); border-color: var(--danger); }
.notice.good { background: color-mix(in srgb, var(--good) 26%, var(--stage-panel)); border-color: var(--good); }

.spawn-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(26rem, 88%);
  padding: 1.1rem 1.2rem;
  border-radius: var(--radius-surface);
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-overlay);
}

.spawn-card h2 { margin: 0 0 .4rem; font-size: var(--type-lede); font-weight: 620; border: 0; padding: 0; }
.spawn-card p { margin: .3rem 0 .8rem; font-size: var(--type-body); }
.spawn-where { font-variant-numeric: tabular-nums; font-weight: 620; }

.panels {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
  border-left: 1px solid var(--line);
}

.tabs { display: flex; border-bottom: 1px solid var(--line); }

.tab {
  flex: 1;
  padding: .55rem .3rem;
  font: inherit;
  font-size: var(--type-ui);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 620; }

.panel { flex: 1; min-height: 0; overflow-y: auto; padding: .7rem .8rem 1.2rem; }
.panel h3 { margin: .8rem 0 .35rem; font-size: var(--type-meta); letter-spacing: .07em; text-transform: uppercase; color: var(--ink-soft); }
.panel h3:first-child { margin-top: 0; }
.small { font-size: var(--type-ui); }

.row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .1rem;
  width: 100%;
  padding: .4rem .5rem;
  margin-bottom: .2rem;
  text-align: left;
  font: inherit;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  color: var(--ink);
  cursor: pointer;
}

.row:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--line); }
.row:disabled { cursor: default; opacity: .65; }
.row-name { font-size: var(--type-ui); font-weight: 620; }
.row-detail { font-size: var(--type-meta); color: var(--ink-soft); }

/* What the keys do, in the panel rather than only in the hint over the stage:
   the hint says what to press now, this says what there is to press. */
.keys { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: .2rem .6rem; }
.keys dt { font-weight: 620; font-size: var(--type-meta); white-space: nowrap; }
.keys dd { margin: 0; font-size: var(--type-meta); color: var(--ink-soft); }

.row-action {
  font-size: var(--type-ui);
  padding: .25rem .5rem;
  margin-right: .35rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink-soft);
  text-decoration: none;
  cursor: pointer;
}

.row-action:hover { color: var(--accent); border-color: var(--accent); }

/* A button in the bar, which is otherwise labels and links. Quieter than an
   .action and louder than a .status, because it is the only way back to the
   identity card once it has been answered (D-267). */
.bar-action {
  font: inherit;
  font-size: var(--type-ui);
  padding: .25rem .55rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line);
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}

.bar-action:hover { color: var(--accent); border-color: var(--accent); }

/* Which of the two things an agent may think with. A brain is a name from a
   list the server sent; a script is Lua you wrote. One is showing at a time,
   so neither can be mistaken for the other (D-255, D-267). */
#employ .choice {
  margin: .6rem 0 .5rem;
  padding: .45rem .55rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
}

#employ .choice legend { font-size: var(--type-meta); color: var(--ink-soft); padding: 0 .3rem; }
#employ .choice label { display: block; font-size: var(--type-ui); cursor: pointer; }
/* An author's `display` beats the browser's rule for [hidden], so the option
   that is taken away has to be taken away here too. */
#employ .choice label[hidden] { display: none; }
#employ .choice input { margin-right: .35rem; }

#chat-panel { display: flex; flex-direction: column; }
#chat-log { flex: 1; min-height: 8rem; overflow-y: auto; margin-bottom: .5rem; }

.chat-line { margin: .25rem 0; max-width: none; font-size: var(--type-ui); line-height: 1.45; }
.chat-who { font-weight: 620; margin-right: .35rem; }
.chat-line.direct .chat-who { color: var(--warn-ink); }
.chat-line.local .chat-who { color: var(--accent); }
.chat-line.mine { color: var(--accent); }
.chat-line.system { color: var(--ink-soft); font-style: italic; }

#chat-form { display: grid; grid-template-columns: auto 1fr; gap: .35rem; }
#chat-form select, #chat-form input, #chat-form button {
  font: inherit;
  font-size: var(--type-ui);
  padding: .35rem .45rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink);
}
#chat-to { grid-column: 1 / -1; }
#chat-text { grid-column: 1 / -1; }
#chat-form button { grid-column: 1 / -1; cursor: pointer; }

.panel details { margin-bottom: .4rem; border: 1px solid var(--line); border-radius: var(--radius-control); }
.panel summary { padding: .35rem .5rem; cursor: pointer; font-size: var(--type-ui); font-weight: 620; }
.panel details pre { margin: 0; border: 0; border-top: 1px solid var(--line); border-radius: 0; font-size: var(--type-meta); max-width: none; }

/* The site's own button, at the size a panel wants. Everything else about it
   — the fill, the border, the weight, the quiet variant — is the site's, and
   saying it twice is how the two drifted apart. */
.action { padding: .45rem .8rem; font-size: var(--type-ui); }

.banner {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .45rem .55rem;
  margin-bottom: .6rem;
  font-size: var(--type-ui);
  border-radius: var(--radius-control);
  background: var(--accent-soft);
  border: 1px solid var(--line);
}

.banner button { margin-left: auto; }

.signin {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--stage-scrim);
  backdrop-filter: blur(8px);
  z-index: 20;
}

.signin-card {
  width: min(27rem, 90%);
  padding: 1.4rem 1.5rem;
  border-radius: var(--radius-surface);
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-overlay);
}

.signin-card h2 { margin: 0 0 .5rem; font-size: var(--type-title); font-weight: 620; border: 0; padding: 0; }
.signin-card label { display: block; margin: .7rem 0 .2rem; font-size: var(--type-meta); color: var(--ink-soft); }

.signin-card input {
  width: 100%;
  font: inherit;
  padding: .45rem .55rem;
  border-radius: var(--radius-control);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink);
}

.signin-actions { display: flex; gap: .6rem; align-items: center; margin-top: 1rem; }

/* The two ways back onto an account, offered without shouting: somebody who has
   neither a passphrase nor a code should not have to read past them. */
.signin-card .problem { color: var(--danger-ink); font-weight: 620; margin: .8rem 0 0; font-size: var(--type-ui); }
.signin-more { margin-top: .9rem; font-size: var(--type-ui); color: var(--ink-soft); }
.signin-more summary { cursor: pointer; }
.signin-more button { margin-top: .6rem; }
.signin-card .muted.small a { color: inherit; }

@media (max-width: 62rem) {
  body.play { overflow: auto; height: auto; display: block; }
  body.play main { height: auto; display: block; }
  .play-bar { flex-wrap: wrap; }
  .play-bar #who-am-i:empty { display: none; }
  .play-body { grid-template-columns: 1fr; }
  .stage { height: 62vh; }
  .panels { border-left: 0; border-top: 1px solid var(--line); max-height: 60vh; }
}

/* ---- a phone ------------------------------------------------------------ */

/* Everything below is the same client at 375 px. Nothing is taken away and
   nothing is added: the stage keeps more than half the screen, the bottom-left
   column becomes the full width of it, and the controls grow to the size of a
   fingertip. */
@media (max-width: 48rem) {
  .stage { height: 56vh; min-height: 20rem; }

  /* The minimap is a nicety and it was taking a third of the width. It also
     moves to the top, because the bottom of a phone is where the thumb is and
     the bottom of this stage is where everything a person presses now lives. */
  #minimap { width: 6.5rem; height: 6.5rem; right: .5rem; top: .5rem; bottom: auto; }

  /* Which leaves the whole width of the bottom for the card and the hint. */
  .stage-foot { left: .5rem; right: .5rem; bottom: .5rem; gap: .4rem; }
  .focus-card { width: 100%; max-height: 45vh; }
  .overlay-line { font-size: var(--type-meta); max-width: 100%; }

  /* Here the hint goes too, not only the card: a phone's bottom third is the
     whole of the usable screen and a question needs all of it. */
  .stage.asking .stage-foot { display: none; }
  .dialogue-card { width: calc(100% - 1rem); bottom: .6rem; }

  /* The tabs are the navigation of the whole panel, so they get a thumb's
     worth of height rather than a mouse pointer's. */
  .tab { padding: .75rem .3rem; font-size: var(--type-ui); }
  .panel { padding: .8rem .8rem 2rem; }
  .panels { max-height: none; }

  /* Chat is the one control that has to be reachable without hunting. */
  #chat-log { min-height: 11rem; }
  #chat-form select, #chat-form input, #chat-form button { font-size: var(--type-body); padding: .55rem .5rem; }

  .signin-card { width: min(27rem, 94%); padding: 1.1rem 1.1rem 1.3rem; }
  .signin-actions { flex-wrap: wrap; }
}

/* A finger, whatever the width of the screen. Everything that is pressed grows
   to something a fingertip can land on; nothing moves and nothing is hidden. */
@media (pointer: coarse) {
  .row-action, .bar-action { font-size: var(--type-ui); padding: .45rem .7rem; margin-right: .4rem; }
  .reach-item { padding: .6rem .8rem; }
  .row { padding: .6rem .55rem; }
  .focus-close { font-size: var(--type-title); padding: .3rem .6rem; }
  .verb-field input[type="text"], .verb-field input[type="number"] { font-size: var(--type-body); padding: .4rem .45rem; }
  .dialogue-answers .action { padding: .6rem 1rem; }
}

/* ---- what you can do to the thing you are looking at ------------------- */

.verbs {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-bottom: 0.9rem;
}

.verb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.verb .row-action {
  flex: 0 0 auto;
}

.verb .row-detail {
  flex: 1 1 100%;
}

.verb-field {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: var(--type-meta);
  color: var(--muted);
}

.verb-field input[type="text"],
.verb-field input[type="number"] {
  width: 9rem;
  padding: 0.2rem 0.35rem;
  font: inherit;
  font-size: var(--type-ui);
}

.verb-field input[type="number"] {
  width: 4.5rem;
}

/* ---- what the world is asking (D-272) ---------------------------------- */

/* Bottom centre rather than the middle of the screen, which is where the
   spawn card sits: a question is usually about the thing you are standing in
   front of, and covering it up to ask about it is unhelpful. */
.dialogue-card {
  position: absolute;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  width: min(30rem, 92%);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  z-index: 10;
}

.dialogue {
  padding: 0.8rem 0.95rem;
  border-radius: var(--radius-surface);
  background: var(--panel);
  border: 1px solid var(--accent-soft);
  box-shadow: var(--shadow-overlay);
}

.dialogue-who {
  margin: 0;
  font-size: var(--type-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.dialogue-question {
  margin: 0.2rem 0 0.6rem;
  font-size: var(--type-lede);
  font-weight: 620;
}

.dialogue-answers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.dialogue .verb-field {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.45rem;
  font-size: var(--type-ui);
}
