/*
  Panels — the site's primary container, and the thing the dossier is made of.

  Document-true: pure black interior, 2px full-phosphor border, SQUARE corners,
  generous padding, floating on the warm grey page. Panels stack vertically with
  a gap; small green annotations live in the gutter BETWEEN them, outside any
  border ("Credentials met / Logged on as: DEV ACCESS").

  Implementation note on the optional title notch (.panel.titled):

  study_desk draws tmux-style titled frames glyph-by-glyph onto a per-pane <canvas>
  in a requestAnimationFrame loop (study_desk.js:drawPaneFrameCanvas). Correct for a
  fixed-size desktop window, wrong for a website — it would need re-rasterising on
  every reflow, the title would not be selectable text, and it costs an animation
  frame forever on a page that is mostly static. So the notch is CSS: a real element
  sitting on the border with the panel background behind it. Identical notch at any
  width, selectable text, zero JS.
*/

.panel {
  position: relative;
  background: var(--pane);
  border: 2px solid var(--border);
  padding: var(--panel-pad);
  min-width: 0;
}

/* Gutter annotation — the small green line that sits between panels, outside
   any border. The document opens on one of these. */
.gutter-note {
  font-family: var(--mono-family);
  font-size: 11px;
  line-height: 1.35;
  color: var(--accent);
  padding: 0 2px;
  margin: -2px 0 0;
  white-space: pre-line;
}
.gutter-note .val { color: var(--ink2); }

/* ---- title notch (wonder heritage, opt-in) ----

   The title must read as being IN the border line, tmux-style, the way both
   source apps draw it:   ━━┫ record://slug ┣━━

   Three things make it read as part of the line instead of pasted on top:

   1. Tee caps. The border visibly TERMINATES into ┫ and resumes from ┣ — heavy
      box-drawing tees, whose stroke at 17px is ~2px, the same weight as the
      border they cap. (The statusbar keeps its light ┤ ├: its rule is a
      hairline. The law is match-the-line, not one-tee-everywhere.)

   2. A two-tone patch. The notch straddles the border: above the line is the
      page (grey), below is the panel (black). A solid patch of either colour
      shows against the other — the old version painted black onto the grey
      page, which is exactly what "pasted on" looks like. This gradient splits
      at the midline, so each half vanishes into its own ground and only the
      border's gap reads.

   3. The tees' vertical bars optically continue the border stroke through
      the gap. */

.panel.titled > .panel-title {
  position: absolute;
  top: 0;
  left: 14px;
  transform: translateY(-50%);
  max-width: calc(100% - 44px);
  padding: 0;
  background: linear-gradient(to bottom, var(--bg) 0 50%, var(--pane) 50% 100%);
  color: var(--label-hi);
  font-family: var(--mono-family);
  font-size: 12.5px;
  line-height: 18px;
  letter-spacing: 0.05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  user-select: none;
}
.panel.titled > .panel-title b { color: var(--accent); font-weight: 600; }

.panel.titled > .panel-flag {
  position: absolute;
  top: 0;
  right: 14px;
  transform: translateY(-50%);
  padding: 0;
  background: linear-gradient(to bottom, var(--bg) 0 50%, var(--pane) 50% 100%);
  font-family: var(--mono-family);
  font-size: 11px;
  line-height: 18px;
  letter-spacing: 0.08em;
  white-space: nowrap;
  user-select: none;
}

.panel.titled > .panel-title::before,
.panel.titled > .panel-title::after,
.panel.titled > .panel-flag::before,
.panel.titled > .panel-flag::after {
  color: var(--border);
  font-size: 17px;
  font-weight: 400;
  letter-spacing: 0;
  vertical-align: -1px;
}
.panel.titled > .panel-title::before { content: "┫"; margin-right: 7px; }
.panel.titled > .panel-title::after  { content: "┣"; margin-left: 7px; }
.panel.titled > .panel-flag::before  { content: "┫"; margin-right: 7px; }
.panel.titled > .panel-flag::after   { content: "┣"; margin-left: 7px; }

.panel.titled.quiet > .panel-title::before,
.panel.titled.quiet > .panel-title::after,
.panel.titled.quiet > .panel-flag::before,
.panel.titled.quiet > .panel-flag::after { color: var(--border2); }

/* ---- focus ----
   Exactly one panel may carry it (wonder brief §3: "focus is a status channel").
   The gradient border is the one wall-clock animation the site keeps, because it
   is chrome, not data. It stops dead under prefers-reduced-motion. */
.panel.focused { border-color: transparent; }
.panel.focused::before {
  content: "";
  position: absolute;
  inset: -2px;
  padding: 2px;
  background: var(--focus-line);
  background-size: 240% 240%;
  animation: focusShift 8s linear infinite;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}
@keyframes focusShift {
  0%   { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .panel.focused::before { animation: none; background-position: 0% 50%; }
}

/* ---- variants ---- */

.panel.quiet { border-color: var(--border2); }
.panel.tight { padding: 18px; }
.panel.flush { padding: 0; }

/* ---- inner rules ----
   The dossier separates panel bands with a thin grey hairline that stops short of
   the border on both sides. Not a border on the content — a rule of its own. */
.hair {
  border: 0;
  border-top: 1px solid var(--border3);
  margin: 22px 0;
}
.hair.tight { margin: 14px 0; }

/* An ASCII rule, for places the document draws one out of glyphs. The glyphs are
   generated by the build so the line always fills its container. */
.rule {
  font-family: var(--mono-family);
  color: var(--border2);
  font-size: 12px;
  line-height: 1;
  overflow: hidden;
  white-space: nowrap;
  user-select: none;
  margin: 18px 0;
}
.rule.green { color: var(--accent-dim); }

/* ---- grids ---- */

.panel-stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap-in);
}

.grid {
  display: grid;
  gap: var(--gap-in);
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.grid.wide { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.grid.duo  { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid > .span-all { grid-column: 1 / -1; }
