/* Cohabyte: the facility.

   THE PALETTE IS THE APP'S (cohabyte/ui/theme.py), read and transcribed, not invented:
   the dark navy family the handset and the Manual are painted in. The one rule of shape
   comes over too: rounded and rubber is hardware (the keys, the doors), chamfered is
   printed paper (the sheets, the dossiers). Consolas, because every UI string in the app is.

   Two kinds of page. The Core (body.core) is one stage, the sphere drawn on a canvas and
   the consoles and doors placed over it. A room (body.room) is a quieter hall: a head
   strip with the room's name and the door back, then the content. Leaving one page for another goes through a WINDOW (doors.js and the block at
   the end of this file): a console is a window to its room; you are pulled toward it,
   a cut, and the window grows to fill the screen. The way back is the opposite: the
   room folds into the console's rectangle and the Mainframe is there behind it. */

:root {
  --bg:         #07070d;   /* window body, the rubber */
  --surface:    #151525;   /* cards, rows, inputs */
  --surface-hi: #1e1e30;   /* hover state of surface */
  --border:     #2a2a5a;   /* the one border colour */
  --border-hi:  #3d3d6b;   /* hovered border */
  --accent:     #7EC8E3;   /* Byte blue, the brand accent */
  --text:       #c8c8e8;   /* primary text */
  --text-hi:    #ffffff;   /* emphasized text */
  --dim:        #888aaa;   /* secondary text */
  --faint:      #555577;   /* tertiary, disabled */
  --primary:    #1c3d52;   /* primary action fill */
  --primary-hi: #254e66;   /* primary action hover */
  --key:        #2a2a42;   /* a key's face */

  --font: Consolas, "Cascadia Mono", "DejaVu Sans Mono", Menlo, monospace;
  --page: 1040px;
  --gutter: 16px;
  --chamfer: 10px;
  --pull: 0.3s;            /* the pull toward a box; doors.js waits this long before it navigates */
  --open: 0.5s;            /* ...and the window growing on the next page */
  --fold: 0.3s;            /* a room folding into its console; doors.js waits this long */
  --cool: 0.2s;            /* ...and the console cooling on the Mainframe */
  --paper: polygon(
    var(--chamfer) 0, calc(100% - var(--chamfer)) 0, 100% var(--chamfer),
    100% calc(100% - var(--chamfer)), calc(100% - var(--chamfer)) 100%,
    var(--chamfer) 100%, 0 calc(100% - var(--chamfer)), 0 var(--chamfer));
}

* { box-sizing: border-box; }

html { background: var(--bg); }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--text-hi); }
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

h1, h2, h3 { color: var(--text-hi); margin: 0; line-height: 1.15; }
p { margin: 0; }

.fine { color: var(--dim); font-size: 13px; }

/* ── Keys and doors: the hardware idiom, rounded and rubber ─────────────── */

.key, .door {
  display: inline-block;
  padding: 9px 18px;
  border-radius: 8px;
  background: var(--key);
  color: var(--text-hi);
  border: 1px solid var(--border);
  border-bottom-width: 3px;              /* the wall, so the key stands off the case */
  line-height: 1.3;
  white-space: nowrap;
}
.key:hover, .door:hover { background: var(--surface-hi); border-color: var(--border-hi); color: var(--text-hi); }
.key:active, .door:active { border-bottom-width: 1px; transform: translateY(2px); }

.key-primary { background: var(--primary); border-color: var(--primary-hi); }
.key-primary:hover { background: var(--primary-hi); border-color: #2f6180; }

.key-inert { color: var(--dim); cursor: default; }
.key-inert:hover { background: var(--key); border-color: var(--border); color: var(--dim); }
.key-inert:active { border-bottom-width: 3px; transform: none; }

.door {
  min-width: 9em;
  text-align: center;
  letter-spacing: 0.06em;
}
.door:hover { box-shadow: 0 0 18px rgba(126, 200, 227, 0.25); border-color: var(--accent); }

/* ── THE CORE ───────────────────────────────────────────────────────────── */

body.core { overflow: hidden; }
body.core .page {
  min-height: 100vh;
  display: grid;
  place-items: center;
}

/* The stage is the whole viewport, whatever its shape: the canvas draws from its
   size, the consoles sit at percentages of it, and the type is set in a stage unit
   (--u, about 13.5px on a 1400x900 window, 21.6px at 2560x1440) so a large screen
   gets a larger Mainframe rather than the same one with more margin. */
.stage {
  position: relative;
  width: 100vw;
  height: 100vh;
  --u: min(1vw, 1.5vh);
}

#core {
  position: absolute;
  inset: 0;
  animation: reveal 1s ease-out both;
}

/* The four consoles are the doors. Each is centred on its coordinate, and the canvas
   reads that centre off the layout to start its conduit there. They are hardware, in
   the key idiom: an opaque face, a firm edge, a wall along the bottom so the plate
   stands off the case, a lamp beside the name. Name and one word of state. */
.consoles { display: contents; }
.console {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 13em;
  padding: 1em 1.3em 0.9em;
  background: linear-gradient(180deg, #23233c, var(--key));
  border: 2px solid var(--border-hi);
  border-bottom-width: 5px;
  border-radius: 10px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
  color: var(--dim);
  font-size: max(12px, calc(var(--u) * 0.9));
  line-height: 1.4;
  letter-spacing: 0.1em;
}
/* Placed off the centre by the smaller of a share of the width and a share of the
   height, so on a wide screen they stay near the sphere instead of at the far edges.
   On a 3:2 stage this is 13 % and 9 % from the sides. */
.console:nth-of-type(1) { left: calc(50% - min(37vw, 58vh)); top: 26%; }
.console:nth-of-type(2) { left: calc(50% + min(37vw, 58vh)); top: 26%; }
.console:nth-of-type(3) { left: calc(50% - min(41vw, 64vh)); top: 68%; }
.console:nth-of-type(4) { left: calc(50% + min(41vw, 64vh)); top: 68%; }
.console { transition: border-color var(--cool) ease-out, box-shadow var(--cool) ease-out; }
.console h2::before { transition: background var(--cool) ease-out, box-shadow var(--cool) ease-out; }
.console:hover, .console:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 26px rgba(126, 200, 227, 0.3), 0 8px 22px rgba(0, 0, 0, 0.55);
  color: var(--text);
}
.console:active { border-bottom-width: 2px; transform: translate(-50%, calc(-50% + 3px)); }
.console h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.25em;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.console h2::before {                    /* the lamp */
  content: "";
  width: 0.55em; height: 0.55em;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent);
}
.console:hover h2::before, .console:focus-visible h2::before { background: var(--text-hi); box-shadow: 0 0 12px var(--text-hi); }
.console .stat { display: block; margin-top: 4px; padding-left: 18px; }

.name {
  position: absolute;
  left: 50%; top: 9%;
  transform: translateX(-50%);
  font-size: max(28px, calc(var(--u) * 2.9));   /* the name leads; the motto sits under it, smaller */
  letter-spacing: 0.32em;
  padding-left: 0.32em;                  /* the tracking's trailing space, balanced */
}

.motto {
  position: absolute;
  left: 50%; top: 16%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 90%;
  text-align: center;
  color: var(--text);
  font-size: max(15px, calc(var(--u) * 1.3));
}

/* The opening, transcribed from the start menu's own splash: the mark (here the sphere)
   over the first second, the name at 1.0 s, the motto at 1.6 s, then the rest. */
.reveal { animation: reveal 0.6s ease-out both; }
.reveal-name  { animation-delay: 1.0s; }
.reveal-motto { animation-delay: 1.6s; }
.console { animation: reveal 0.6s ease-out both; animation-delay: 2.4s; }

@keyframes reveal { from { opacity: 0; } to { opacity: 1; } }

/* Back from a room: everything is already there. */
.returning .reveal, .returning .console, .returning #core { animation: none; }

/* A phone holds the stage upright: the sphere in the middle, two consoles above it and
   two below, the name and motto at the top. */
@media (max-width: 760px) {
  .name  { top: 5%; font-size: 24px; }
  .motto { top: 10.5%; font-size: 14px; }
  .console { font-size: 11px; padding: 0.8em 1.1em 0.7em; }
  .console:nth-of-type(1) { left: 27%; top: 25%; }
  .console:nth-of-type(2) { left: 73%; top: 25%; }
  .console:nth-of-type(3) { left: 27%; top: 79%; }
  .console:nth-of-type(4) { left: 73%; top: 79%; }
}

/* ── A ROOM ─────────────────────────────────────────────────────────────── */

body.room .page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* The room's scenery (rooms.js) is a canvas across the whole page, under the head
   strip and the readouts. It lives inside .page so a window's scale carries it. */
.scene { position: absolute; inset: 0; z-index: 0; }
.roomhead, .roombody { position: relative; z-index: 1; }

.roomhead {
  max-width: var(--page);
  width: 100%;
  margin: 0 auto;
  padding: 18px var(--gutter);
  display: flex;
  align-items: center;
  gap: 22px;
  border-bottom: 1px solid var(--border);
}
.roomhead h1 {
  font-size: 18px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.roomhead .crumb { color: var(--faint); }
.roomhead .crumb::after { content: "  /  "; white-space: pre; }
.door-back { min-width: 0; }
.door-back::before { content: "\2190\00a0"; }

.roombody {
  max-width: var(--page);
  width: 100%;
  margin: 0 auto;
  padding: 40px var(--gutter) 56px;
  flex: 1;
}

.roomsub { font-size: 16px; margin: 36px 0 16px; }
.lede { max-width: 62ch; margin-bottom: 24px; }

.about {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}
.about img { width: 96px; flex: none; }
.about h2 { font-size: 22px; }
.about p:last-child { max-width: 62ch; margin-top: 12px; }

/* ── Sheets: printed paper, chamfered ───────────────────────────────────── */

.sheet {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;                              /* the rule between cells is the case showing through */
  background: var(--border);
  clip-path: var(--paper);
}
.sheet > div { background: var(--surface); padding: 18px 20px; }
.sheet dt { color: var(--accent); font-weight: bold; margin-bottom: 4px; }
.sheet dd { margin: 0; }

.sheet.compact { grid-template-columns: 1fr; }
.sheet.compact > div { display: grid; grid-template-columns: 10ch 1fr; gap: 12px; padding: 12px 18px; }
.sheet.compact dt { margin: 0; }

/* ── The pose row (Records) ─────────────────────────────────────────────── */

.poses {
  list-style: none;
  margin: 40px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}
.poses li {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;                    /* a screen on the handset: hardware */
}
.poses img { width: 150px; }
.poses span { color: var(--dim); }

/* ── The bays (Assembly) ────────────────────────────────────────────────── */

.bays {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: minmax(150px, auto);
  gap: 16px;
}
.bay {
  position: relative;
  padding: 36px 18px 18px;
  background: var(--surface);
  clip-path: var(--paper);
}
.bayno {
  position: absolute;
  left: 14px; top: 10px;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--faint);
}

.bay.lit {
  grid-column: 1 / span 2;
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 20px;
  align-items: start;
  background: linear-gradient(180deg, #1a1a30, var(--surface));
}
.bay.lit .bayno { color: var(--accent); }
.bay.lit img { width: 150px; align-self: center; }
.bay.lit h2 { font-size: 20px; }

.bay.dark {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 4px;
  color: var(--dim);
}
.bay.dark h2 { font-size: 12px; color: var(--faint); letter-spacing: 0.1em; margin-top: 8px; }
.bay.dark:only-of-type, .bays .bay.dark { min-height: 180px; }
.bay.dark .bio { margin-top: 6px; font-size: 12px; color: var(--faint); }

.spec {
  width: 100%;
  margin-top: 10px;
  border-collapse: collapse;
  font-size: 14px;
}
.spec th, .spec td { text-align: left; vertical-align: top; padding: 5px 0; border-top: 1px solid var(--border); }
.spec th { color: var(--dim); font-weight: normal; width: 15ch; padding-right: 12px; }
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 1px solid var(--border); }

.bio { margin-top: 14px; font-style: italic; }

.lock {
  position: relative;
  width: 44px; height: 44px;
  flex: none;
  border: 1px solid var(--border);
}
.lock::before {                          /* the shackle */
  content: "";
  position: absolute;
  left: 14px; top: 8px;
  width: 12px; height: 13px;
  border: 3px solid var(--faint);
  border-bottom: 0;
  border-radius: 9px 9px 0 0;
}
.lock::after {                           /* the body */
  content: "";
  position: absolute;
  left: 11px; top: 21px;
  width: 22px; height: 15px;
  background: var(--faint);
  border-radius: 3px;
}

/* ── Dispatch ───────────────────────────────────────────────────────────── */

.download { display: grid; gap: 16px; justify-items: start; }
.download-key { display: grid; gap: 8px; justify-items: start; }

/* ── Narrow screens ─────────────────────────────────────────────────────── */

@media (max-width: 820px) {
  .poses { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bays { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .download { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .sheet { grid-template-columns: 1fr; }
  .sheet.compact > div { grid-template-columns: 1fr; gap: 2px; }
  .poses img { width: 110px; }
  .bays { grid-template-columns: 1fr; }
  .bay.lit { grid-column: 1; grid-row: auto; grid-template-columns: 1fr; justify-items: center; }
  .spec th { width: 12ch; }
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .console, #core { animation: none; }
  .key:active, .door:active { transform: none; }
  body, .page, .pull, .window, .console, .console h2::before { animation: none !important; transition: none !important; }
  .window { display: none !important; }
}

/* ── The windows ────────────────────────────────────────────────────────── */

/* Leaving: the page scales about the clicked box (doors.js sets the origin inline)
   and dims behind it; the box stays lit above the dim. */
.page { position: relative; }
.pull {
  position: absolute;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--pull) ease-in;
}
.pull.on { opacity: 0.6; }
.console.hot, .door.hot {
  z-index: 60;
  border-color: var(--accent);
  box-shadow: 0 0 26px rgba(126, 200, 227, 0.45);
}
.door.hot { position: relative; }
.console.hot h2::before { background: var(--text-hi); box-shadow: 0 0 12px var(--text-hi); }
.leaving .page { transform: scale(1.25); transition: transform var(--pull) ease-in; }

/* Arriving: the body is clipped to the saved rectangle (the custom properties are set
   before first paint by the inline head script) and the page is a little large; the
   frame sits on the rectangle. doors.js swaps arriving for entering on the same frame,
   and clip, scale and frame all move under a transition. Everything outside the clip
   is the html background, which is the black. */
.arriving body, .entering body {
  clip-path: inset(var(--wy) calc(100vw - var(--wx) - var(--ww)) calc(100vh - var(--wy) - var(--wh)) var(--wx));
}
.arriving .page { transform: scale(1.1); }
.entering body  { clip-path: inset(0 0 0 0); transition: clip-path var(--open) ease-out; }
.entering .page { transform: none; transition: transform var(--open) ease-out; }

.window {
  display: none;
  position: fixed;
  z-index: 100;
  pointer-events: none;
  top: var(--wy); left: var(--wx);
  right: calc(100vw - var(--wx) - var(--ww));
  bottom: calc(100vh - var(--wy) - var(--wh));
  border: 2px solid var(--accent);
  border-radius: 10px;
  box-shadow: 0 0 28px rgba(126, 200, 227, 0.5), inset 0 0 18px rgba(126, 200, 227, 0.25);
}
.arriving .window, .entering .window { display: block; }
.entering .window {
  inset: -10px;                          /* off the edges, then the glow goes too */
  opacity: 0;
  transition: inset var(--open) ease-out, opacity 0.15s ease-out calc(var(--open) - 0.1s);
}

/* Folding back: doors.js first parks the frame at the edges with the clip open
   (framed), settles that, then sets the console's rectangle and folds; clip, frame
   and scale all move under a transition, ease-in, the room drawing back. */
.framed body  { clip-path: inset(0 0 0 0); }
.framed .window { display: block; inset: -10px; opacity: 1; }
.folding body {
  clip-path: inset(var(--wy) calc(100vw - var(--wx) - var(--ww)) calc(100vh - var(--wy) - var(--wh)) var(--wx));
  transition: clip-path var(--fold) ease-in;
}
.folding .page { transform: scale(1.1); transition: transform var(--fold) ease-in; }
.folding .window {
  top: var(--wy); left: var(--wx);
  right: calc(100vw - var(--wx) - var(--ww));
  bottom: calc(100vh - var(--wy) - var(--wh));
  transition: inset var(--fold) ease-in;
}

/* Arriving back: the Mainframe is full on the first frame with the frame on the
   console (doors.js has lit it); the frame cools away and the console with it. */
.arriving-back .window, .entered-back .window { display: block; }
.entered-back .window { opacity: 0; transition: opacity var(--cool) ease-out; }
