/*
 * writeup.css — THE WRITE-UPS SURFACE: the wall of records and the sheet
 * of record (2026-10-25 redesign; direction.md "THE WALL AND THE RECORD").
 *
 * Two surfaces, one file:
 *   - writeups_gallery (extends base.html): the dark ARCHIVE WALL listing
 *     record cards — machined surfaces, sans/mono voices, NO serif (serif
 *     lives on paper; paper begins when a sheet is opened).
 *   - writeup_page / writeup_missing (standalone, strict CSP
 *     `default-src 'self'; style-src 'self' 'unsafe-inline'`): PAPER —
 *     .artifact sheets floating on the bare wall. Machine evidence (flags,
 *     commands, terminal captures) is framed in dark wells ON the sheet;
 *     the human narrative is Source Serif on paper.
 *
 * The standalone pages link fonts.css + tokens.css + base.css +
 * components.css + this sheet (base.css carries the reset, focus law,
 * scrollbars and the reduced-motion kill-switch; components.css carries
 * .artifact/.artifact-well/.btn/.pill primitives). writeup.js (frozen,
 * CSP-safe) builds .copy-btn, .cast-bar/.cast-screen and the ANSI hue
 * spans — this sheet styles them; it never scripts them.
 *
 * Laws honored here: every color is a token (zero orphan hexes); paper
 * tokens appear only inside .writeup-sheet / .writeup-slip (the artifact
 * roots); states never ship color-alone (icon + label); no emoji; motion
 * stays under the global kill-switch.
 */

/* ==========================================================================
 * 1. standalone page chrome — the bare wall around the paper
 * ========================================================================== */
.writeup-standalone {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  padding-inline: var(--sp-3);
}

.writeup-wallbar {
  width: 100%;
  max-width: 792px; /* the sheet (760) plus its breathing room, aligned */
  margin: 0 auto;
  padding: var(--sp-4) var(--sp-1) 0;
}

.writeup-back {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: 0.04em;
  color: var(--text-label);
  text-decoration: none;
}
.writeup-back:hover { color: var(--sig); text-decoration: none; }

/* ==========================================================================
 * 2. the sheet of record — paper reading column
 * ========================================================================== */
.writeup-sheet {
  width: 100%;
  max-width: 760px;
  margin: var(--sp-4) auto var(--sp-16);
  padding: var(--sp-12) var(--sp-8) var(--sp-12);
  /* Reading column: serif runs a step above the UI scale (the 12px floor
     holds; documents read larger than instruments). */
  font-size: 17px;
  line-height: 1.7;
  animation: sheet-seat var(--t-settle) var(--ease-drawer) both;
}

@keyframes sheet-seat {
  from { transform: translateY(10px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* -- sheet head: masthead, facts, stamps -------------------------------- */
.writeup-sheet-head { margin-bottom: var(--sp-6); }
.writeup-sheet .writeup-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-3);
  font-family: var(--font-sans);
  font-size: var(--t-meta);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--paper-faint);
}

.writeup-sheet .writeup-title {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-serif);
  font-size: var(--t-display-2);
  line-height: var(--t-display-2-lh);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--paper-ink);
  overflow-wrap: anywhere;
}

.writeup-facts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-4);
}

/* Category tag: the name carries identity; the channel hue rides as a
   3px side rule (decorative — no contrast burden on paper). */
.writeup-sheet .writeup-cat {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--sp-2);
  border: 1px solid var(--paper-rule);
  border-left-width: 3px;
  border-radius: var(--r-chamfer);
  background: var(--paper-well);
  font-family: var(--font-sans);
  font-size: var(--t-meta);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--paper-ink);
}
.writeup-cat.cat-pwn       { border-left-color: var(--cat-pwn); }
.writeup-cat.cat-web       { border-left-color: var(--cat-web); }
.writeup-cat.cat-crypto    { border-left-color: var(--cat-crypto); }
.writeup-cat.cat-rev       { border-left-color: var(--cat-rev); }
.writeup-cat.cat-forensics { border-left-color: var(--cat-forensics); }
.writeup-cat.cat-misc      { border-left-color: var(--cat-misc); }
.writeup-cat.cat-stego     { border-left-color: var(--cat-stego); }
.writeup-sheet .writeup-cat.cat-unknown   { border-left-color: var(--paper-faint); }
.writeup-sheet .writeup-fact { font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--paper-muted); }
.writeup-sheet .writeup-fact b { margin-right: var(--sp-1);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--paper-faint); }

/* The state pill is machine vocabulary: mount it on a dark inset so the
   channel hues (validated against dark surfaces) hold on paper. */
.writeup-sheet .pill,
.writeup-slip .pill {
  background: var(--s-pit);
  border-color: var(--line-soft);
}

/* Validation verdict — a chip, never a stamp (the stamp is the submit
   ceremony and nothing else borrows its shape). Icon carries the hue;
   the word carries the meaning. */
.writeup-sheet .writeup-verdict {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-2);
  border: 1px solid var(--paper-rule);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--paper-ink);
}
.writeup-verdict--validated { border-color: var(--st-good); }
.writeup-verdict--validated .icon { color: var(--st-good); }
.writeup-verdict--failed { border-color: var(--st-serious); }
.writeup-verdict--failed .icon { color: var(--st-serious); }
.writeup-sheet .writeup-verdict--draft .icon { color: var(--paper-faint); }

/* The ledger line: points, solvers, solved-at, provenance, actions. */
.writeup-stamps {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--paper-rule);
}
.writeup-stamp {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--paper-muted);
}
.writeup-stamp b {
  margin-right: var(--sp-1);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--paper-faint);
}
.writeup-sheet form,
.writeup-slip form {
  display: inline-flex;
  margin: 0;
}
.writeup-sheet /* ui-e4: provenance line beside the verdict. */
.validation-source { font-family: var(--font-sans);
  font-size: var(--t-ui);
  color: var(--paper-muted); }
.writeup-sheet .validation-source b { font-weight: 600; color: var(--paper-ink); }

/* Ghost buttons are graphite chrome; on paper they take paper ink. */
.writeup-sheet .btn-ghost,
.writeup-slip .btn-ghost { color: var(--paper-muted); }
.writeup-sheet .btn-ghost:hover,
.writeup-slip .btn-ghost:hover {
  background: var(--paper-well);
  color: var(--paper-ink);
}
.writeup-sheet /* ==========================================================================
 * 3. exhibit bars — the boxed EXHIBIT lines (ui-e2)
 *    Contracts pinned by tests + writeup.js: exact class strings
 *    "flag-bar copyable" / "reproduce-bar copyable", .writeup-sheet data-copy-text.
 * ========================================================================== */
.flag-bar, .writeup-sheet .reproduce-bar { position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--paper-well);
  border: 1px solid var(--paper-rule);
  border-left: 3px solid var(--ink-on-paper-accent);
  border-radius: var(--r-chamfer); }
.writeup-sheet .flag-bar b, .writeup-sheet .reproduce-bar b { flex: none;
  font-family: var(--font-sans);
  font-size: var(--t-meta);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--paper-faint); }
.writeup-sheet .flag-bar code { flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--t-title);
  font-weight: 600;
  color: var(--paper-ink);
  overflow-wrap: anywhere; }
.reproduce-bar {
  margin: 0 0 var(--sp-6);
}
.writeup-sheet .reproduce-bar .code-box { flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  font-family: var(--font-mono);
  font-size: var(--t-ui);
  line-height: 1.55;
  color: var(--paper-ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere; }
.writeup-sheet /* ==========================================================================
 * 4. proof — the flag-moment evidence (E1)
 * ========================================================================== */
.proof-missing { display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-6);
  padding: var(--sp-3);
  border: 1px dashed var(--st-warn);
  border-radius: var(--r-chamfer);
  background: var(--st-warn-dim);
  color: var(--paper-ink);
  font-size: var(--t-ui);
  line-height: 1.55; }
.proof-missing .icon {
  flex: none;
  margin-top: 2px;
  color: var(--st-warn);
}
.writeup-sheet .proof-hero { display: grid;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--paper-rule); }
.writeup-sheet .proof-title { margin: 0;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--paper-faint); }
.proof-frame,
.proof-media {
  margin: 0;
  display: grid;
  gap: var(--sp-2);
}
.writeup-sheet .proof-frame img, .writeup-sheet .proof-media video { display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--paper-rule);
  border-radius: var(--r-chamfer);
  background: var(--paper-well); }
.proof-media video { background: var(--s-void); }
.writeup-sheet .proof-frame figcaption, .writeup-sheet .proof-media figcaption { font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--paper-muted);
  overflow-wrap: anywhere; }
.proof-frame figcaption::before {
  content: "▸ ";
  color: var(--st-good);
}

/* ==========================================================================
 * 5. the terminal wells — ANSI player + timed cast (writeup.js builds the
 *    chrome: .cast-bar > .cast-play/.cast-speed/.cast-clock, .cast-screen)
 *
 *    The machine voice framed on the record: an artifact-well shape with
 *    terminal darkness. Hue classes map to the RESERVED status tokens
 *    (>= 7:1 on --s-pit); bright = high-intensity --text-max.
 * ========================================================================== */
.ansi-player {
  padding: var(--sp-3);
  background: var(--s-pit);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-ui);
  line-height: 1.55;
  color: var(--text-body);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow: auto;
  max-height: 26rem;
  min-height: 4.5rem;
  transition: border-color var(--t-fast) var(--ease-snap);
}
.ansi-player a { color: var(--st-info); }
.ansi-player .ansi-r { color: var(--st-serious); }
.ansi-player .ansi-g { color: var(--st-good); }
.ansi-player .ansi-y { color: var(--st-warn); }
.ansi-player .ansi-b { color: var(--st-info); }
.ansi-player .ansi-bright { color: var(--text-max); }
.ansi-player .ansi-bold { font-weight: 600; }
.ansi-player.is-error { color: var(--st-serious); }
.ansi-player.is-playing { border-color: var(--st-good); }

/* timed .cast playthrough */
.ansi-player.is-timed {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.cast-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 0 var(--sp-2);
  border-bottom: 1px solid var(--line-soft);
}
.cast-play { min-width: 5.5rem; }
.cast-speed {
  padding: 2px var(--sp-2);
  background: var(--s-card);
  border: 1px solid var(--line);
  border-radius: var(--r-chamfer);
  color: var(--text-body);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
}
.cast-clock {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-label);
  font-variant-numeric: tabular-nums;
}
.cast-screen {
  margin: 0;
  min-height: 16rem;
  max-height: 24rem;
  overflow-y: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ==========================================================================
 * 6. the artifact ledger — inventory rows on the sheet
 * ========================================================================== */
.writeup-sheet .writeup-gallery {
  margin: 0 0 var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--paper-rule);
}
.writeup-sheet .writeup-gallery-title { margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--paper-faint); }
.writeup-gallery ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.writeup-sheet .writeup-gallery li { display: grid;
  gap: var(--sp-1);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--paper-rule); }
.writeup-gallery li:last-child { border-bottom: none; }
.writeup-gallery a {
  font-family: var(--font-mono);
  font-size: var(--t-ui);
  color: var(--ink-on-paper-accent);
  overflow-wrap: anywhere;
}
.writeup-gallery a:hover { text-decoration: underline; }
.writeup-artifact-meta {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--paper-muted);
}
.writeup-sheet /* raw .cast/.ansi previews collapse behind a toggle; the dump itself is a
   dark well, .writeup-sheet same as the player — machine text on the record. */
.preview-details summary { font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--paper-muted);
  cursor: pointer;
  user-select: none; }
.writeup-sheet .preview-details summary::marker { color: var(--paper-faint); }
.preview {
  padding: var(--sp-2) var(--sp-3);
  background: var(--s-pit);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-body);
  overflow: auto;
  max-height: 14rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ==========================================================================
 * 7. the narrative — .writeup-body (server-sanitized markdown)
 *    Element set fixed by render.py: h1-h6, p, ul/ol/li, blockquote,
 *    pre>code, inline code, a, img (same-origin artifacts only), table, hr.
 *    writeup.js queries ".writeup-body pre" for copy buttons.
 * ========================================================================== */
.writeup-sheet .writeup-body {
  padding-top: var(--sp-5);
  border-top: 1px solid var(--paper-rule);
}
.writeup-body > :first-child { margin-top: 0; }
.writeup-body > :last-child { margin-bottom: 0; }
.writeup-sheet .writeup-body h1, .writeup-sheet .writeup-body h2, .writeup-sheet .writeup-body h3, .writeup-sheet .writeup-body h4 { font-family: var(--font-serif);
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.25;
  margin: var(--sp-8) 0 var(--sp-3);
  color: var(--paper-ink); }
.writeup-sheet .writeup-body h1 { font-size: var(--t-display-2);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--paper-rule); }
.writeup-body h2 { font-size: var(--t-title-lg); }
.writeup-body h3 { font-size: var(--t-title); }
.writeup-sheet .writeup-body h4 { font-size: var(--t-title);
  font-style: italic;
  color: var(--paper-muted); }

.writeup-body p,
.writeup-body ul,
.writeup-body ol,
.writeup-body blockquote,
.writeup-body pre,
.writeup-body table {
  margin: 0 0 var(--sp-4);
}
.writeup-body ul { padding-left: var(--sp-5); }
.writeup-body li { margin-bottom: var(--sp-2); }
.writeup-body li:last-child { margin-bottom: 0; }
.writeup-sheet .writeup-body li::marker { color: var(--paper-faint); }

/* Numbered steps (E1): an ordered list is the procedure — mono numerals in
   the paper accent carry it, not decimal dots. Nested lists revert. */
.writeup-body ol {
  list-style: none;
  padding-left: 0;
  counter-reset: p2g-step;
}
.writeup-body ol > li {
  counter-increment: p2g-step;
  position: relative;
  padding-left: 2.75rem;
  margin-bottom: var(--sp-4);
}
.writeup-body ol > li::before {
  content: counter(p2g-step);
  position: absolute;
  left: 0;
  top: -0.1rem;
  min-width: 2rem;
  font-family: var(--font-mono);
  font-size: var(--t-title-lg);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink-on-paper-accent);
  text-align: right;
}
.writeup-body ol ol { list-style: decimal; padding-left: var(--sp-5); }
.writeup-body ol ol > li { padding-left: 0; margin-bottom: var(--sp-2); }
.writeup-body ol ol > li::before { content: none; }

/* Prose links stay underlined — a reader skims, not hunts. */
.writeup-body a {
  color: var(--ink-on-paper-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.writeup-body a:hover { text-decoration-thickness: 2px; }
.writeup-sheet /* inline code chip */
.writeup-body code { font-family: var(--font-mono);
  font-size: 0.85em;
  padding: 0.08em 0.35em;
  background: var(--paper-well);
  border: 1px solid var(--paper-rule);
  border-radius: var(--r-chamfer);
  overflow-wrap: anywhere; }

/* block code — a terminal well on the sheet; position: relative hosts the
   copy button writeup.js injects. */
.writeup-body pre {
  position: relative;
  padding: var(--sp-3);
  background: var(--s-pit);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-ui);
  line-height: 1.6;
  color: var(--text-body);
  overflow-x: auto;
}
.writeup-body pre code {
  padding: 0;
  background: none;
  border: none;
  font-size: inherit;
  color: inherit;
}
.writeup-sheet /* blockquote — a margin note in the record's voice. */
.writeup-body blockquote { padding: var(--sp-1) 0 var(--sp-1) var(--sp-4);
  border-left: 2px solid var(--paper-rule);
  font-style: italic;
  color: var(--paper-muted); }
.writeup-sheet .writeup-body img { display: block;
  max-width: 100%;
  height: auto;
  margin: 0 0 var(--sp-4);
  border: 1px solid var(--paper-rule);
  border-radius: var(--r-chamfer);
  background: var(--paper-well); }

.writeup-body table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--t-ui);
}
.writeup-sheet .writeup-body th, .writeup-sheet .writeup-body td { padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--paper-rule);
  text-align: left; }
.writeup-sheet .writeup-body th { background: var(--paper-well);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--paper-muted); }
.writeup-sheet .writeup-body hr { border: none;
  border-top: 1px solid var(--paper-rule);
  margin: var(--sp-6) 0; }

/* ==========================================================================
 * 8. copy buttons — injected by writeup.js on .writeup-body pre and
 *    .copyable[data-copy-text]. Two contexts: dark wells (absolute) and
 *    paper exhibit bars (inline, end of the flex row).
 * ========================================================================== */
.copy-btn {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  padding: 2px var(--sp-2);
  background: var(--s-card);
  border: 1px solid var(--line);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-label);
  cursor: pointer;
  transition:
    color var(--t-fast) var(--ease-snap),
    border-color var(--t-fast) var(--ease-snap),
    background var(--t-fast) var(--ease-snap);
}
.copy-btn:hover { color: var(--text-max); border-color: var(--line-tick); }
.copy-btn:focus-visible { box-shadow: var(--focus-ring); }
.copy-btn.is-copied { color: var(--st-good); border-color: var(--st-good); }
.copy-btn.is-failed { color: var(--st-serious); border-color: var(--st-serious); }
.writeup-sheet .flag-bar .copy-btn, .writeup-sheet .reproduce-bar .copy-btn { position: static;
  margin-left: auto;
  background: var(--paper);
  border-color: var(--paper-rule);
  color: var(--paper-muted); }
.writeup-sheet .flag-bar .copy-btn:hover, .writeup-sheet .reproduce-bar .copy-btn:hover { border-color: var(--paper-muted);
  color: var(--paper-ink); }
.writeup-sheet .flag-bar .copy-btn.is-copied, .writeup-sheet .reproduce-bar .copy-btn.is-copied { border-color: var(--st-good);
  color: var(--paper-ink); }
.writeup-sheet .flag-bar .copy-btn.is-failed, .writeup-sheet .reproduce-bar .copy-btn.is-failed { border-color: var(--st-serious);
  color: var(--paper-ink); }

/* ==========================================================================
 * 9. sheet foot + the missing slip
 * ========================================================================== */
.writeup-sheet-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
  padding-top: var(--sp-4);
  border-top: 2px solid var(--paper-rule);
}
.writeup-sheet-end {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--paper-faint);
}
.writeup-sheet .writeup-back--paper { color: var(--paper-muted); }
.writeup-sheet .writeup-back--paper:hover { color: var(--paper-ink); }

/* A small paper slip: the record does not exist yet. */
.writeup-slip {
  width: 100%;
  max-width: 520px;
  margin: auto; /* centers on the wall, short page and all */
  padding: var(--sp-8) var(--sp-6);
  font-size: var(--t-title);
  line-height: 1.6;
  animation: sheet-seat var(--t-settle) var(--ease-drawer) both;
}
.writeup-slip .writeup-sheet-head { margin-bottom: 0; }
.writeup-slip .proof-missing { margin: var(--sp-5) 0 0; }
.writeup-slip-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}

/* ==========================================================================
 * 10. the archive wall — writeups gallery (dark; extends base.html)
 * ========================================================================== */
.writeups-wall {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-4) var(--sp-12);
}

.writeups-wallhead {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
.writeups-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-label);
}
.writeups-title {
  margin: 0 0 var(--sp-2);
  font-size: var(--t-display-2);
  line-height: var(--t-display-2-lh);
  color: var(--text-max);
}
.writeups-desc {
  margin: 0;
  font-size: var(--t-ui);
  color: var(--text-body);
}
.writeups-wallhead-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.writeups-count {
  padding: 2px var(--sp-2);
  background: var(--s-pit);
  border: 1px solid var(--line);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-label);
}

.record-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--sp-4);
}

/* record card: dark wall furniture wearing the write-up channel hue —
   everything on this wall is archived to the record. */
.record-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--sp-4);
  background: var(--s-card);
  border: 1px solid var(--line);
  border-top: 2px solid var(--ch-writeup);
  border-radius: var(--r-chamfer);
  box-shadow: var(--shadow-bevel);
  transition:
    background var(--t-fast) var(--ease-snap),
    border-color var(--t-fast) var(--ease-snap);
}
.record-card:hover {
  background: var(--s-card-hi);
  border-color: var(--line-tick);
  border-top-color: var(--ch-writeup);
}

.record-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
.record-doc { color: var(--ch-writeup); }

/* category chip: glyph + name, hue from the ledger (label-mandatory pair). */
.record-cat {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  max-width: 100%;
  padding: 2px var(--sp-2);
  background: var(--s-pit);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-body);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.record-cat.cat-pwn       { color: var(--cat-pwn); }
.record-cat.cat-web       { color: var(--cat-web); }
.record-cat.cat-crypto    { color: var(--cat-crypto); }
.record-cat.cat-rev       { color: var(--cat-rev); }
.record-cat.cat-forensics { color: var(--cat-forensics); }
.record-cat.cat-misc      { color: var(--cat-misc); }
.record-cat.cat-stego     { color: var(--cat-stego); }
.record-cat.cat-unknown   { color: var(--cat-misc); border-style: dashed; }

.record-points {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  font-variant-numeric: tabular-nums;
  color: var(--text-label);
}

.record-title {
  margin: 0 0 var(--sp-3);
  color: var(--text-max);
  overflow-wrap: anywhere;
}

/* flag on record — redacted on the wall; the copy-paste exhibit is on the
   sheet itself. */
.record-flag {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--s-pit);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-chamfer);
  color: var(--text-label);
}
.record-flag code {
  font-family: var(--font-mono);
  font-size: var(--t-ui);
  color: var(--text-body);
  overflow-wrap: anywhere;
}
.record-flag-lbl {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-label);
}

.record-meta {
  display: grid;
  gap: 2px;
  margin-bottom: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  color: var(--text-label);
}
.writeup-solver { color: var(--text-body); font-weight: 600; }
.record-avail {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  color: var(--ch-writeup);
}

.record-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line-soft);
}
.record-state {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.record-state--validated { color: var(--st-good); }
.record-state--failed { color: var(--st-serious); }
.record-state--draft { color: var(--text-label); }
.record-read { margin-left: auto; }

/* empty wall */
.writeups-empty {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-12) var(--sp-4);
  background: var(--s-card); /* pinned: modals.css keeps a stale .writeups-empty */
  border: 1px dashed var(--line);
  border-radius: var(--r-chamfer);
  text-align: center;
  color: var(--text-label);
}
.writeups-empty .icon-xl { color: var(--text-faint); }
.writeups-empty-title {
  margin: var(--sp-2) 0 0;
  font-size: var(--t-title);
  color: var(--text-max);
}
.writeups-empty-desc {
  margin: 0 0 var(--sp-3);
  font-size: var(--t-ui);
  color: var(--text-body);
}

/* ==========================================================================
 * 11. bridge — .badge for writeup_composer_modal
 *     The composer (modals.css surface) renders <span class="badge">; the
 *     old writeup.css styled it site-wide. Token-legal restyle until the
 *     modal slice renames it. NOT part of the paper sheet.
 * ========================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 1px var(--sp-2);
  background: var(--s-pit);
  border: 1px solid var(--line);
  border-radius: var(--r-chamfer);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-label);
}
.badge.validated { color: var(--st-good); border-color: var(--st-good); }
.badge.failed { color: var(--st-serious); border-color: var(--st-serious); }

/* ==========================================================================
 * 12. narrow viewports — one column, nothing clipped
 * ========================================================================== */
@media (max-width: 640px) {
  .writeup-standalone { padding-inline: var(--sp-2); }
  .writeup-sheet {
    margin: var(--sp-3) auto var(--sp-8);
    padding: var(--sp-6) var(--sp-4) var(--sp-8);
    font-size: 16px;
  }
  .writeup-title { font-size: var(--t-title-lg); }
  .flag-bar code { font-size: var(--t-ui); }
  .writeup-body table { font-size: var(--t-meta); }
  .writeup-body ol > li { padding-left: 2.25rem; }

  .writeups-wall { padding: var(--sp-4) var(--sp-3) var(--sp-8); }
  .writeups-wallhead { align-items: flex-start; flex-direction: column; }
  .record-grid { grid-template-columns: 1fr; }
  .record-foot .record-read { margin-left: 0; }
}

/* ==========================================================================
 * 13. reduced motion — the sheet is simply there
 *     (base.css carries the global kill-switch; this makes the intent
 *     local and explicit.)
 * ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .writeup-sheet,
  .writeup-slip { animation: none; }
  .record-card,
  .ansi-player,
  .copy-btn { transition: none; }
}
