/* Pip-Boy 3000 Mk IV — monochrome phosphor green on a dark CRT. */

:root {
  /* Every colour below is mixed from --green, so changing this one value reskins
     the whole screen (try #ffb642 for the Pip-Boy's amber setting). */
  --green: #1aff8b;
  --bg-deep: #060807;
  --bg: color-mix(in srgb, var(--green) 5%, var(--bg-deep));
  --bg-lit: color-mix(in srgb, var(--green) 9%, var(--bg-deep));
  --green-mid: color-mix(in srgb, var(--green) 62%, transparent);
  --green-dim: color-mix(in srgb, var(--green) 38%, transparent);
  --green-faint: color-mix(in srgb, var(--green) 16%, transparent);
  --green-wash: color-mix(in srgb, var(--green) 6%, transparent);
  --glow: color-mix(in srgb, var(--green) 45%, transparent);
  --green-bloom: color-mix(in srgb, var(--green) 26%, transparent);
  --green-haze: color-mix(in srgb, var(--green) 5%, transparent);
  --mono: "Share Tech Mono", "Consolas", "Lucida Console", "DejaVu Sans Mono", monospace;
  --box: 34px;
  --box-gap: 8px;

  /* Every font-size in this file is multiplied by this. Raise it if the text
     still reads small — 1.3 and 1.4 both hold up without breaking the layout. */
  --text-scale: 1.45;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background:
    radial-gradient(ellipse 120% 90% at 50% 40%, var(--bg-lit) 0%, var(--bg) 55%, var(--bg-deep) 100%);
  color: var(--green);
  font-family: var(--mono);
  font-size: calc(16px * var(--text-scale));
  letter-spacing: 0.03em;
  text-shadow: 0 0 5px var(--glow);
  min-height: 100vh;
}

::selection { background: var(--green); color: var(--bg-deep); text-shadow: none; }

/* ---------- CRT overlays ---------- */

.crt-lines,
.crt-vignette,
.crt-sweep {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 40;
}

.crt-lines {
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0 2px,
    rgba(0, 0, 0, 0.22) 2px 4px
  );
}

.crt-vignette {
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0.62) 100%);
}

.crt-sweep {
  inset: auto 0 0 0;
  height: 40vh;
  background: linear-gradient(to bottom, transparent, var(--green-haze), transparent);
  animation: sweep 8s linear infinite;
}

@keyframes sweep {
  from { transform: translateY(-140%); }
  to { transform: translateY(240%); }
}

/* ---------- boot / lock states ---------- */

/* The page starts as `html.booting`, which shows only a connecting notice. Once
   the server answers, app.js swaps it for `locked` (keypad) or nothing (app),
   so neither the app nor the keypad ever flashes before the server has spoken. */
.boot { display: none; }
html.booting .boot { display: flex; }
html.booting .topbar,
html.booting .panel,
html.booting .lock { display: none; }

.lock { display: none; }
html.locked .lock { display: flex; }
html.locked .topbar,
html.locked .panel { display: none; }

.boot {
  position: relative;
  z-index: 30;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}

.boot-msg {
  margin: 0;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: center;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.6;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-mid);
}
.boot-msg b {
  font-weight: normal;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: 0.22em;
  color: var(--green);
  text-shadow: 0 0 9px var(--glow);
}
.boot-msg span { text-transform: none; letter-spacing: 0.06em; }
.boot-msg code {
  font-family: inherit;
  color: var(--green);
  border-bottom: 1px solid var(--green-dim);
}

.lock {
  position: relative;
  z-index: 30;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}

.lock-box {
  width: 100%;
  max-width: 340px;
  border: 1px solid var(--green-dim);
  background: var(--green-wash);
  box-shadow: inset 0 0 30px var(--green-haze);
  padding: 26px 22px 22px;
  text-align: center;
}

.lock-brand {
  margin: 0;
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--green-dim);
}

.lock-title {
  margin: 10px 0 0;
  font-size: calc(19px * var(--text-scale));
  font-weight: normal;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-shadow: 0 0 9px var(--glow);
}

.lock-pips {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin: 22px 0 0;
}
.lock-pips span {
  width: 14px;
  height: 14px;
  border: 1px solid var(--green-mid);
}
.lock-pips span.on {
  background: var(--green);
  border-color: var(--green);
  box-shadow: 0 0 9px var(--glow);
}

.lock-msg {
  margin: 16px 0 0;
  min-height: 18px;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-mid);
}
.lock-msg.deny { color: var(--green); animation: blink 0.45s steps(1, end) 3; }

.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin: 20px 0 0;
}

.key {
  padding: 15px 0;
  font: inherit;
  font-size: calc(20px * var(--text-scale));
  color: var(--green);
  background: transparent;
  border: 1px solid var(--green-mid);
  text-shadow: inherit;
  cursor: pointer;
  transition: background 0.1s ease, color 0.1s ease;
}
.key:hover,
.key:focus-visible {
  background: var(--green);
  border-color: var(--green);
  color: var(--bg-deep);
  text-shadow: none;
  outline: none;
}
.key:active { transform: scale(0.96); }
.key-alt { font-size: calc(14px * var(--text-scale)); letter-spacing: 0.1em; text-transform: uppercase; }

.lock-help {
  margin: 20px 0 0;
  padding: 0;
  font: inherit;
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-dim);
  background: none;
  border: 0;
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}
.lock-help:hover { color: var(--green-mid); }

.lock-note {
  margin: 14px 0 0;
  font-size: calc(11px * var(--text-scale));
  line-height: 1.65;
  text-align: left;
  color: var(--green-mid);
}
.lock-note code {
  font-family: inherit;
  color: var(--green);
  border-bottom: 1px solid var(--green-dim);
}

/* ---------- top bar ---------- */

.topbar {
  max-width: 1140px;
  margin: 0 auto;
  padding: 18px 10px 10px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--green-mid);
  border-bottom: 1px solid var(--green-dim);
}

.topbar .brand { color: var(--green); }
.topbar-right { display: flex; align-items: baseline; gap: 16px; }

.ghost-btn {
  background: transparent;
  border: 1px solid var(--green-dim);
  color: var(--green-mid);
  font: inherit;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-shadow: inherit;
  padding: 4px 14px;
  cursor: pointer;
}
.ghost-btn:hover,
.ghost-btn:focus-visible {
  background: var(--green);
  border-color: var(--green);
  color: var(--bg-deep);
  text-shadow: none;
  outline: none;
}

/* ---------- panel ---------- */

.panel {
  max-width: 1140px;
  margin: 0 auto 44px;
  padding: 24px clamp(12px, 3vw, 30px) 32px;
}

.special-nav {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  margin-bottom: 10px;
}

.letter {
  flex: 1;
  background: none;
  border: 0;
  padding: 2px 0 4px;
  font-family: inherit;
  font-size: clamp(calc(28px * var(--text-scale)), 5.6vw, calc(58px * var(--text-scale)));
  line-height: 1;
  color: var(--green-dim);
  text-shadow: none;
  cursor: pointer;
  transition: color 0.12s ease, text-shadow 0.12s ease;
}
.letter:hover { color: var(--green-mid); }
.letter:focus-visible { outline: 1px solid var(--green-dim); outline-offset: 2px; }

.letter .glyph { display: inline-block; padding-bottom: 5px; }
.letter .lvl {
  display: block;
  font-size: clamp(calc(11px * var(--text-scale)), 1.3vw, calc(14px * var(--text-scale)));
  letter-spacing: 0.1em;
  margin-top: 7px;
  opacity: 0.75;
}

.letter[aria-selected="true"] {
  color: var(--green);
  text-shadow: 0 0 10px var(--glow);
}
.letter[aria-selected="true"] .glyph { border-bottom: 2px solid var(--green); }

.stars {
  display: flex;
  justify-content: center;
  gap: clamp(3px, 0.7vw, 9px);
  margin: 16px 0 6px;
}
.stars svg {
  width: clamp(calc(20px * var(--text-scale)), 2.6vw, calc(30px * var(--text-scale)));
  height: auto;
  display: block;
  filter: drop-shadow(0 0 4px var(--glow));
}

.stat-line {
  text-align: center;
  margin: 8px 0 26px;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: 0.1em;
  color: var(--green-mid);
}
.stat-line b { color: var(--green); letter-spacing: 0.22em; text-transform: uppercase; }
.stat-line i { font-style: normal; opacity: 0.8; }

.stat-line .warn {
  color: var(--green);
  letter-spacing: 0.14em;
  animation: blink 1.4s steps(1, end) infinite;
}
@keyframes blink { 50% { opacity: 0.35; } }

/* ---------- cards ---------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: clamp(12px, 2vw, 20px);
}

.card {
  position: relative;
  border: 1px solid var(--green-dim);
  background: var(--green-wash);
  box-shadow: inset 0 0 26px var(--green-haze);
  padding: 20px 16px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Bracket corners, like a Pip-Boy selection frame. */
.card::before,
.card::after {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  border: 1px solid var(--green);
  opacity: 0.7;
}
.card::before { top: -1px; left: -1px; border-width: 2px 0 0 2px; }
.card::after { bottom: -1px; right: -1px; border-width: 0 2px 2px 0; }

.card-art {
  width: min(185px, 60%);
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center;
  border: 1px solid var(--green-dim);
  /* #phosphor (defined in index.html) maps luminance onto the screen's green. */
  filter: url(#phosphor) contrast(1.12);
  opacity: 0.95;
}
body.art-color .card-art { filter: none; opacity: 1; }

.card h2 {
  font-size: calc(19px * var(--text-scale));
  font-weight: normal;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 18px 0 0;
  text-shadow: 0 0 8px var(--glow);
}

.card .quote {
  margin: 14px 0 0;
  font-size: calc(14px * var(--text-scale));
  line-height: 1.5;
  color: var(--green-mid);
}

.card .act {
  margin: 14px 0 0;
  font-size: calc(14px * var(--text-scale));
  line-height: 1.5;
}
.card .act span {
  color: var(--green-mid);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ---------- carousel position markers ---------- */

.dots {
  display: none;
  justify-content: center;
  gap: 10px;
  margin: 20px 0 0;
}

.dot {
  width: 11px;
  height: 11px;
  padding: 0;
  border: 1px solid var(--green-mid);
  background: transparent;
  cursor: pointer;
  transition: background 0.15s ease, box-shadow 0.15s ease;
}
.dot[aria-current="true"] {
  background: var(--green);
  border-color: var(--green);
  box-shadow: 0 0 8px var(--glow);
}
.dot:focus-visible { outline: 1px solid var(--green); outline-offset: 3px; }

/* ---------- check track ---------- */

/* Everything below the action text is bottom-anchored, so the tracks, status
   lines and buttons all line up across the three cards no matter how many lines
   the quote and action wrap to. The cards are equal height already: grid and
   flex both stretch them. */
.card-foot {
  margin-top: auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.track {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  justify-content: center;
  gap: var(--box-gap);
  margin: 20px auto 0;
  max-width: 226px; /* fits 5 boxes per row */
  /* A 7-check perk wraps to two rows; reserve that height for 3s and 5s too so
     the first row of boxes sits at the same height on every card. */
  min-height: calc(var(--box) * 2 + var(--box-gap));
}

.box {
  width: var(--box);
  height: var(--box);
  padding: 0;
  border: 1px solid var(--green-mid);
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.12s ease, transform 0.08s ease, box-shadow 0.12s ease;
}
.box:disabled { cursor: default; border-color: var(--green-dim); }
.box:not(:disabled):hover { background: var(--green-faint); }
.box:not(:disabled):active { transform: scale(0.94); }
.box:focus-visible { outline: 1px solid var(--green); outline-offset: 2px; }

.box svg { width: 22px; height: 22px; display: none; }
.box.filled {
  background: var(--green);
  border-color: var(--green);
  box-shadow: 0 0 9px var(--glow);
}
.box.filled svg { display: block; }
.box.today { outline: 1px dashed var(--green); outline-offset: 3px; }

.progress {
  margin: 14px 0 0;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green-mid);
  min-height: 17px;
}

.log-btn {
  margin-top: 12px;
  width: 100%;
  max-width: 226px;
  padding: 10px;
  font: inherit;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--green);
  background: transparent;
  border: 1px solid var(--green-mid);
  text-shadow: inherit;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.log-btn:hover,
.log-btn:focus-visible {
  background: var(--green);
  border-color: var(--green);
  color: var(--bg-deep);
  text-shadow: none;
  outline: none;
}
.log-btn.done { border-style: dashed; color: var(--green-mid); }

/* ---------- toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 30px;
  transform: translate(-50%, 16px);
  background: var(--bg-deep);
  color: var(--green);
  border: 1px solid var(--green);
  box-shadow: 0 0 22px var(--green-bloom);
  padding: 12px 24px;
  font-size: calc(15px * var(--text-scale));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 45;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.bad { border-style: dashed; }

/* ---------- dialog ---------- */

dialog {
  border: 1px solid var(--green);
  box-shadow: 0 0 30px var(--green-bloom);
  background: var(--bg-deep);
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0 2px,
    rgba(0, 0, 0, 0.22) 2px 4px
  );
  color: var(--green);
  padding: 0;
  max-width: 580px;
  width: calc(100% - 32px);
  font-family: var(--mono);
  text-shadow: 0 0 5px var(--glow);
}
dialog::backdrop { background: rgba(0, 0, 0, 0.72); }

.dlg-body { padding: 20px 22px 22px; }
.dlg-body h2 {
  margin: 0 0 6px;
  font-size: calc(17px * var(--text-scale));
  font-weight: normal;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.dlg-body p.hint {
  margin: 0 0 18px;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.55;
  color: var(--green-mid);
}
.dlg-body h3 {
  margin: 22px 0 10px;
  font-size: calc(12px * var(--text-scale));
  font-weight: normal;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--green-mid);
  border-bottom: 1px solid var(--green-dim);
  padding-bottom: 6px;
}

.level-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(88px * var(--text-scale)), 1fr));
  gap: 10px;
}
.level-grid label {
  /* Column layout keeps every input aligned even when a name wraps. */
  display: flex;
  gap: 5px;
  overflow-wrap: anywhere;
  flex-direction: column;
  height: 100%;
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green-mid);
}
.level-grid input {
  width: 100%;
  margin-top: auto;
  padding: 6px;
  font: inherit;
  color: var(--green);
  background: var(--green-wash);
  border: 1px solid var(--green-dim);
  text-shadow: inherit;
}
.level-grid input:focus-visible { outline: 1px solid var(--green); border-color: var(--green); }

.pin-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.pin-fields label {
  flex: 1 1 calc(130px * var(--text-scale));
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green-mid);
}
.pin-fields input {
  width: 100%;
  padding: 7px;
  font: inherit;
  letter-spacing: 0.4em;
  color: var(--green);
  background: var(--green-wash);
  border: 1px solid var(--green-dim);
  text-shadow: inherit;
}
.pin-fields input:focus-visible { outline: 1px solid var(--green); border-color: var(--green); }

.pin-state {
  margin: 0 0 12px;
  font-size: calc(12px * var(--text-scale));
  line-height: 1.6;
  color: var(--green-mid);
}
.pin-state b { color: var(--green); letter-spacing: 0.1em; text-transform: uppercase; }

.toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: 0.1em;
  color: var(--green-mid);
  cursor: pointer;
}
.toggle input { accent-color: var(--green); width: 16px; height: 16px; cursor: pointer; }

.row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.row button {
  font: inherit;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 8px 14px;
  color: var(--green);
  background: transparent;
  border: 1px solid var(--green-dim);
  text-shadow: inherit;
  cursor: pointer;
}
.row button:hover,
.row button:focus-visible {
  background: var(--green);
  border-color: var(--green);
  color: var(--bg-deep);
  text-shadow: none;
  outline: none;
}
.row button.danger { border-style: dashed; }

.history {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  max-height: 168px;
  overflow-y: auto;
  overflow-x: hidden;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0.06em;
  overflow-wrap: anywhere;
  scrollbar-color: var(--green-dim) transparent;
}
.history li {
  padding: 4px 0;
  border-bottom: 1px solid var(--green-faint);
  color: var(--green-mid);
}
.history .up { color: var(--green); }
.history .down { color: var(--green-dim); }
.history .empty { color: var(--green-dim); }

/* One card at a time below this width, swiped horizontally. The 6% side padding
   leaves a sliver of the neighbouring cards visible so the swipe is discoverable,
   and lets scroll-snap centre the first and last card.

   The breakpoint is 900px rather than a phone width on purpose: three 255px
   columns plus gaps stop fitting below roughly 865px, and the grid would drop to
   two columns with the third card orphaned on its own row. Carousel below,
   clean three-across above. */
@media (max-width: 900px) {
  .cards {
    display: flex;
    gap: 12px;
    padding: 2px 6%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .cards::-webkit-scrollbar { display: none; }

  .cards > .card {
    flex: 0 0 100%; /* 100% of the padded content box == 88% of the panel */
    scroll-snap-align: center;
  }

  .dots { display: flex; }
}

@media (max-width: 560px) {
  .card { padding: 16px 12px 16px; }
  .card-art { width: min(160px, 55%); }

  /* Side by side, the larger type breaks the date across several lines. Stack
     the bar so the date gets the full width and stays on one. */
  .topbar {
    letter-spacing: 0.1em;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .topbar-right { justify-content: space-between; }
}

@media (prefers-reduced-motion: reduce) {
  .crt-sweep { display: none; }
  .stat-line .warn { animation: none; text-decoration: underline; }
}
