/* Klutsis collage — implements DESIGN.md Part I. Fixed palette, do not extend. */

:root {
    --ink:        #1c1a17;
    --paper:      #ded3bd;
    --paper-dark: #c9bb9e;
    --gray:       #8c8579;
    --red:        #b3311f;
    --blue:       #2b4f6b;

    /* One diagonal axis for the entire site. Every rotation derives from these and
       they all share a sign — nothing on any page leans the other way. */
    --axis:       -3deg;
    --axis-soft:  -1.6deg;
    --axis-hard:  -5deg;

    /* Exactly one accent is live per page. Red is the default voice; blue belongs
       to the chat alone. The other never appears on the same screen. */
    --accent:     var(--red);

    --agitprop: Arial, Helvetica, sans-serif;
    --body-serif: 'Times New Roman', Times, serif;
}

body.accent-blue { --accent: var(--blue); }

body.klutsis {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--body-serif);
    min-height: 100vh;
    position: relative;
    overflow-x: hidden;
}

/* paper grain — subtle, this is stock, not a screen glow */
.canvas-grain {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    opacity: 0.5;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/></svg>");
}

.stage {
    position: relative;
    z-index: 1;
}

/* halftone — ink dots on paper, the printed-photograph substitute */
.halftone {
    background-image: radial-gradient(circle, rgba(28,26,23,0.55) 1.2px, transparent 1.6px);
    background-size: 6px 6px;
}

/* agitprop type: bold, blocky, shouted, set as an object rather than a caption */
.agit {
    font-family: var(--agitprop);
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    margin: 0;
}

/* mis-registered print effect: an accent echo offset behind the black type.
   Block-level with matched width so multi-line text wraps identically in both layers.
   Never give a .reg element padding — the echo is laid out against the padding box, so
   padding shifts the two layers apart and prints the word twice. Use margin to inset it. */
.reg {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
}
.reg::before {
    content: attr(data-text);
    position: absolute;
    inset: 0;
    left: 3px;
    top: 3px;
    z-index: -1;
    color: var(--accent);
}

/* Extruded letterform: a stack of hard 1px steps building a solid edge-face, the way
   a built letter shows its side. This is not a drop shadow — no gap, no blur, no
   transparency, and the face is ONE flat palette tone from the glyph to its far edge.
   It used to terminate in a darker --ink step, on the theory that the form needed to
   end on an edge; what that actually did was print a dark rim under the gray, which is
   the one thing an extrusion must not look like — a shadow behind the letter rather
   than the side of it. Only for large type; below ~40px the face closes up the
   counters. Never combine with .reg — the two put different things behind the same
   glyph. */
.extrude {
    text-shadow:
        1px 1px 0 var(--gray),  2px 2px 0 var(--gray),  3px 3px 0 var(--gray),
        4px 4px 0 var(--gray),  5px 5px 0 var(--gray),  6px 6px 0 var(--gray),
        7px 7px 0 var(--gray),  8px 8px 0 var(--gray),  9px 9px 0 var(--gray),
       10px 10px 0 var(--gray);
}

.kicker {
    font-family: var(--agitprop);
    font-weight: 700;
    letter-spacing: 0.25em;
    text-transform: uppercase;
    font-size: 12px;
    margin: 0 0 8px;
}

/* --- cut paper ---------------------------------------------------------- */

/* A cut/torn panel: irregular edge, hard zero-blur offset shadow.
   Tears are measured in PIXELS, never percentages — a torn edge is a constant
   physical size and must not scale with the sheet. The invariant is per-edge:
   padding on an edge must exceed the deepest tear inset on that edge. These panel
   tears cut up to 14px, so anything wearing one keeps >= 16px of padding. */
.cut-panel {
    position: relative;
    background: var(--paper-dark);
    box-shadow: 9px 9px 0 rgba(28,26,23,0.85);
    padding: 26px 24px;
}

.cut-1 {
    clip-path: polygon(0 6px, 8px 0, calc(100% - 10px) 4px, 100% 0,
                       calc(100% - 4px) calc(100% - 9px), calc(100% - 13px) 100%,
                       7px calc(100% - 5px), 0 100%);
}
.cut-2 {
    clip-path: polygon(4px 0, 100% 5px, calc(100% - 6px) calc(100% - 4px),
                       calc(100% - 14px) calc(100% - 9px), 9px 100%, 0 calc(100% - 11px));
}
.cut-3 {
    clip-path: polygon(0 9px, 11px 0, calc(100% - 5px) 3px, 100% 12px,
                       calc(100% - 3px) 100%, 5px calc(100% - 6px), 0 calc(100% - 13px));
}

/* Rotation is a property of SMALL things: drift is height x sin(angle), so a tall
   column sheared even 1.5deg walks its own text tens of pixels across the page.
   Never put .tilt* on an element taller than ~600px — give the lean to a header
   slab laid across it instead. */
/* --axis-hard has no .tilt-hard class: everything that needs it is a motif already
   carrying its own absolute positioning, so it takes rotate(var(--axis-hard)) inside
   that rule rather than a second class in the markup. */
.tilt      { transform: rotate(var(--axis)); }
.tilt-soft { transform: rotate(var(--axis-soft)); }

/* torn button: a stapled-on paper tab, not a rounded UI button */
/* 19px is a contrast floor, not a taste call: --paper on --red is 4.19:1, which passes
   only as large text — 14pt/18.67px at this weight. At the inherited 16px every red
   button on the site was the same accent-as-small-type failure as the byline and the
   comment stamp before it. A button that needs to be smaller than this steps down to
   .cut-btn--ink (11.7:1), which is legible at any size; it never shrinks on the accent. */
.cut-btn {
    display: inline-block;
    font-family: var(--agitprop);
    font-size: 19px;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-decoration: none;
    padding: 15px 26px;
    color: var(--paper);
    box-shadow: 6px 6px 0 rgba(28,26,23,0.85);
    border: none;
    clip-path: polygon(0 4px, calc(100% - 9px) 0, 100% 8px,
                       calc(100% - 4px) 100%, 6px calc(100% - 3px), 0 calc(100% - 8px));
}
/* primary carries the page's one accent; secondary steps down to ink, never to
   the other accent colour */
.cut-btn--accent { background: var(--accent); }
.cut-btn--ink    { background: var(--ink); }

.system-bar {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    padding: 12px 18px;
    font-family: var(--agitprop);
    font-size: 11px;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--ink);
}
/* the username is user-supplied and up to 20 chars — it truncates rather than
   shoving the nav link off the screen */
.system-bar span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.system-bar a {
    flex: none;
    color: var(--ink);
    text-decoration: none;
    border-bottom: 2px solid var(--accent);
}

/* --- motifs -------------------------------------------------------------
   A motif is a montage fragment, not an ornament: it is always either cropped by
   a page/container edge or overlapped by type. Nothing floats with clear space
   around it, and nothing sits where it can occlude a line of text. */

.motif {
    display: block;
    pointer-events: none;
}

/* The beam is drawn as an <img>, not a CSS mask: a mask image is CORS-restricted and
   silently renders nothing when the page and the asset differ in origin — which is
   exactly the situation any offline/file:// screenshot pass puts it in. beam.svg is
   red, and the beam only ever appears on red-accent pages, so nothing is lost. */

/* --- masthead ----------------------------------------------------------- */

.masthead {
    position: relative;
    padding: 30px 20px 26px;
    overflow: hidden;
}

.masthead .kicker {
    position: relative;
    z-index: 2;
    margin-bottom: 14px;
}

.masthead .wordmark {
    position: relative;
    z-index: 2;
}

.wordmark {
    font-size: clamp(38px, 12vw, 66px);
    line-height: 0.94;
    transform: rotate(var(--axis));
    transform-origin: 0 50%;
    color: var(--ink);
    margin-bottom: 6px;
}

/* --- hub ---------------------------------------------------------------- */

/* Not a grid of equal cards. One dominant panel and one subordinate one, offset
   and overlapping, differing by SCALE — the beam runs behind both and off both
   edges, so the motif is structural rather than a corner sticker. */
.hub-stack {
    position: relative;
    max-width: 560px;
    margin: 0 auto;
    padding: 40px 20px 100px;
}

.hub-axis {
    position: absolute;
    left: -200px;
    top: -30px;
    width: 560px;
    transform: rotate(12deg);
    z-index: 0;
}

.hub-tile { position: relative; z-index: 1; }

.hub-tile--major { width: 100%; }
.hub-tile--minor {
    width: 72%;
    margin-left: auto;
    margin-top: -22px;
    z-index: 2;
}

/* the third fragment continues the cascade rather than restoring a grid: each tile
   is smaller than the one above it and offset the other way */
.hub-tile--footnote {
    width: 56%;
    margin-top: -14px;
    z-index: 3;
}

.hub-tile--minor .cut-panel    { padding: 20px 20px 22px; }
.hub-tile--footnote .cut-panel { padding: 16px 16px 18px; }

.hub-tile h2 { margin: 0 0 8px; }
.hub-tile--major h2    { font-size: 32px; }
.hub-tile--minor h2    { font-size: 18px; }
.hub-tile--footnote h2 { font-size: 14px; }

.hub-tile p {
    font-family: var(--body-serif);
    margin: 0 0 20px;
}
.hub-tile--major p    { font-size: 15px; }
.hub-tile--minor p    { font-size: 13px; }
.hub-tile--footnote p { font-size: 12px; margin-bottom: 14px; }

/* the tiles' scale cascade runs through their buttons too. Both of these are
   .cut-btn--ink, which is why they're allowed below the accent's 19px floor */
.hub-tile--minor .cut-btn {
    padding: 12px 20px;
    font-size: 15px;
    box-shadow: 5px 5px 0 rgba(28,26,23,0.85);
}
.hub-tile--footnote .cut-btn {
    padding: 10px 16px;
    font-size: 11px;
    box-shadow: 4px 4px 0 rgba(28,26,23,0.85);
}

/* the disc column steps down in scale across the seam between the two tiles,
   cropped by the right edge of the page */
.hub-discs {
    position: absolute;
    right: -26px;
    top: -74px;
    width: 52px;
    transform: rotate(var(--axis));
    z-index: 3;
}

/* --- blog --------------------------------------------------------------- */

.blog-wrap {
    position: relative;
    max-width: 640px;
    margin: 0 auto;
    padding: 26px 20px 90px;
}

/* --- blog screen head ---
   The index's header is one flat plate of colour with the word screened out of it.
   Everything on the site until now put its texture in the GROUND — the halftone
   rectangle behind the hub masthead, the paper grain — and left the type solid. This
   inverts that: the plate is flat, and the only screen on the page is inside the
   letterforms, which is what a printed poster actually looks like and what a dot
   pattern behind a second dot pattern never will.

   The rule that came out of building it: **one screen per composition.** Texture in
   the type means the ground under it stays flat, and vice versa. Two rulings in one
   header fight each other and read as noise rather than as printing.

   The accent is spent here as a full plate cropped by both page edges — a block, which
   is what rule 4 allows — and the type on it is --paper, never the accent itself.
   No motif: a disc column in the corner could be deleted without moving anything else,
   and rule 5 calls that decoration. */

.screen-head {
    position: relative;
    padding: 46px 20px 26px;
    overflow: hidden;
}

.screen-plate {
    position: absolute;
    left: -34px;
    right: -34px;
    top: -10px;
    height: 156px;
    background: var(--accent);
    transform: rotate(var(--axis));
    z-index: 0;
}

/* The dots are var(--paper) at a 4px ruling, just large enough to touch across the
   cell, so the word reads as a screened solid rather than a dotted outline. Paper on
   --red is 4.19:1 solid, and at this size the type clears the large-text floor with
   room; it would not at body size, which is why this device is only ever a wordmark. */
.screen-mark {
    position: relative;
    z-index: 2;
    font-size: clamp(38px, 12.8vw, 62px);
    line-height: 1.06;
    margin: 4px 0 0;
    color: var(--paper);
    background-image: radial-gradient(circle, var(--paper) 2.05px, transparent 2.25px);
    background-size: 4px 4px;
    transform: rotate(var(--axis));
    transform-origin: 0 50%;
}

/* Only knock the fill out where the browser can actually paint the screen into the
   glyphs. Without the guard, a browser that ignores background-clip renders a
   transparent word on a red plate — an invisible masthead. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .screen-mark {
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
    }
}

/* an ink tab on the plate, which is where the second tone has to go: the plate is the
   accent and the type on it is paper, so the kicker cannot be either */
.screen-kicker {
    position: relative;
    z-index: 2;
    display: inline-block;
    margin: 30px 0 0;
    padding: 9px 14px 8px;
    background: var(--ink);
    color: var(--paper);
    clip-path: polygon(0 3px, 6px 0, calc(100% - 5px) 2px, 100% 6px,
                       calc(100% - 3px) 100%, 4px calc(100% - 4px), 0 calc(100% - 7px));
}

.post { position: relative; margin: 0 0 64px; }

/* the tilt lives on the small header slab; the body column below stays axis-true
   because rotating a 3000px column shears its own text across the viewport */
/* an ink slab pasted across the top of the paper column — the seam between the two
   fragments has to be visible, or the pair just reads as one card with a crooked edge */
.post-head {
    position: relative;
    z-index: 2;
    margin: 0 0 -16px;
    padding: 18px 20px 16px;
    background: var(--ink);
}

.post-head h1,
.post-head h2 {
    font-size: 22px;
    line-height: 1.15;
    margin: 0 0 6px;
    color: var(--paper);
}

.post-head h2 a {
    color: inherit;
    text-decoration: none;
}
/* hover moves the accent to a rule under the words rather than tinting them —
   see the note on .byline below */
.post-head h2 a:hover {
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-decoration-thickness: 3px;
    text-underline-offset: 4px;
}

.post--full .post-head { width: 92%; }
.post--full .post-head h1 { font-size: 25px; }

/* The accent is spent as AREA, never as a tint on small type. 11px --red on the
   --ink slab measures 2.79:1 — under every legibility floor there is. The colour
   goes down as a solid block at full strength and the words step to --gray, which
   is a structural palette tone and clears 4.5:1 on ink. */
.post-head .byline {
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--agitprop);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--gray);
    margin: 0;
}

.post-head .byline::before {
    content: "";
    flex: none;
    width: 22px;
    height: 7px;
    background: var(--accent);
}

.post-body {
    position: relative;
    z-index: 1;
    padding: 30px 22px 24px;
}

.post-body p {
    line-height: 1.65;
    font-size: 16px;
    margin: 0 0 16px;
}
.post-body p:last-child { margin-bottom: 0; }

/* --- incident in the long column ---
   A full post is the longest uninterrupted run of text on the site. Left alone it
   sets as an ordinary document, which is the one register this project is trying
   not to fall back into. Three interruptions, none of them decoration: the opening
   paragraph is set larger so the column starts at a different scale, a numbered
   stanza mark breaks it at intervals, and a motif passes behind the panel. */

.post--full .post-body > p:first-of-type {
    font-size: 19px;
    line-height: 1.5;
    margin-bottom: 22px;
}

.stanza {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 30px 0 26px;
    transform: rotate(var(--axis-soft));
}

.stanza-block {
    flex: none;
    width: 34px;
    height: 9px;
    background: var(--accent);
}

.stanza-num {
    flex: none;
    font-size: 13px;
    letter-spacing: 0.18em;
    color: var(--gray);
}

/* the hard rule fills whatever is left of the line, running off the panel's edge */
.stanza-rule {
    flex: 1;
    height: 2px;
    background: var(--ink);
    opacity: 0.35;
}

/* Behind the panel, not inside it: .post-body carries a clip-path, and a clip-path
   clips descendants — a motif hung off the panel's edge from inside gets sliced.
   The paper panel covers all but a sliver, so it reads as cropped twice over and
   never lands on a line of text. */
.post-mark {
    position: absolute;
    right: -46px;
    top: 32%;
    width: 122px;
    transform: rotate(var(--axis-hard));
    z-index: 0;
}

.post-actions {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin: 22px 0 0;
}

.comment-count {
    font-family: var(--agitprop);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.empty-note {
    font-family: var(--agitprop);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 13px;
}

/* --- comments ------------------------------------------------------------
   The same two-fragment grammar as a post, one step down in scale: a small ink
   name tab pasted across the corner of a paper strip. */

.comments {
    position: relative;
    margin: 72px 0 0;
}

/* cropped by the right edge of the page, with the section head running past it */
.comments-discs {
    position: absolute;
    right: -30px;
    top: -30px;
    width: 46px;
    transform: rotate(var(--axis));
    z-index: 0;
}

.comments-head {
    position: relative;
    z-index: 1;
    font-size: clamp(26px, 8vw, 40px);
    transform: rotate(var(--axis));
    transform-origin: 0 50%;
    margin: 0 0 30px;
}

.comment { margin: 0 0 34px; }

.comment-tag {
    position: relative;
    z-index: 2;
    display: inline-block;
    margin: 0 0 -12px 10px;
    padding: 7px 14px;
    background: var(--ink);
    color: var(--paper);
    font-size: 12px;
    letter-spacing: 0.14em;
    clip-path: polygon(0 3px, 6px 0, calc(100% - 5px) 2px, 100% 6px,
                       calc(100% - 3px) 100%, 4px calc(100% - 4px), 0 calc(100% - 7px));
}

.comment-body {
    position: relative;
    z-index: 1;
    padding: 24px 22px 18px;
    font-size: 15px;
    line-height: 1.6;
}
.comment-body > p { margin: 0; }

/* No opacity. A tint of --ink over --paper-dark is exactly the accent-as-tint
   mistake in a different colour: 0.55 measures 3.17:1, worse than the byline that
   already had to be fixed. Small type is a flat palette tone at full strength and
   gets its quietness from SIZE, not from being faded — see rule 7. */
.comment-body > .comment-stamp {
    font-family: var(--agitprop);
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink);
    margin-top: 14px;
}

.comment-form { margin: 44px 0 0; }

.comment-as { margin-bottom: 12px; }

.comment-form textarea {
    font-size: 16px;
    resize: none;
    margin-bottom: 26px;
}

/* --- login -------------------------------------------------------------- */

/* Flush left, not centred: the panel is one fragment pasted onto a field the beam
   crosses from corner to corner, cropped by both edges. A column, because the sheet
   carries two masses now — the panel and the type stand under it. */
.login-stage {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    /* not centred as one lump: the two masses are spread down the sheet so a tall
       phone doesn't leave its bottom third as bare, uncomposed paper */
    justify-content: space-evenly;
    padding: 40px 20px;
    box-sizing: border-box;
    position: relative;
    overflow: hidden;
}

/* Static. Nothing on this site moves: these are fragments of paper cut and pasted
   down, and the one ambient drift that used to run here — an 11s pass along the
   beam's own axis — read as a hero image easing about, which is the register the
   whole project is built to avoid. The rotation lives on the element now because
   it used to live in the keyframes. */
.login-beam {
    position: absolute;
    left: -200px;
    top: 50%;
    width: 660px;
    margin-top: -330px;
    opacity: 0.9;
    z-index: 0;
    transform: rotate(14deg);
}

/* the same beam again at a fraction of the size — repetition at shrinking scale,
   not a second shape */
.login-beam--echo {
    left: auto;
    right: -70px;
    top: 20%;
    width: 190px;
    margin-top: 0;
    opacity: 0.55;
}

.login-block {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 316px;
}

/* The wordmark is a sibling laid ON the panel, not a heading inside it: a clip-path
   clips every descendant, so type that bleeds past a torn edge has to live outside
   the panel or the tear eats it. */
.login-wordmark {
    position: relative;
    z-index: 2;
    font-size: clamp(34px, 11vw, 52px);
    margin: 0 0 -20px 4px;
}

.login-panel {
    position: relative;
    box-sizing: border-box;
    padding-top: 34px;
}

.login-panel .kicker { margin-bottom: 16px; }

/* form controls are cut paper too — a shallower tear (insets <= 8px) so it stays well
   inside the 16px padding and can never reach what's being typed */
.cut-input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    font-family: var(--body-serif);
    font-size: 20px;
    padding: 14px 16px;
    background: var(--paper);
    color: var(--ink);
    border: none;
    box-shadow: 4px 4px 0 rgba(28,26,23,0.6);
    clip-path: polygon(0 3px, 5px 0, calc(100% - 6px) 2px, 100% 0,
                       calc(100% - 2px) calc(100% - 5px), calc(100% - 8px) 100%,
                       4px calc(100% - 3px), 0 100%);
}

.login-panel .cut-input { margin: 0 0 20px; }

.cut-btn.full {
    display: block;
    width: 100%;
    text-align: center;
    box-sizing: border-box;
}

/* --- the type stand ---
   Type as a built object, after the constructed letters on the 1922 propaganda stand:
   two words are two planes at different heights, each with its own solid edge-face,
   thrown in OPPOSITE directions so the forms cross each other in depth instead of
   stacking. The site's .extrude is one plane and reads as a treatment; two planes
   crossing read as a structure, which is what the reference actually is.

   It also stops the login being the one page that leaves the bottom third of its sheet
   as bare, uncomposed paper. This is the second mass the composition needed, and it
   says something true about the page: there is no password, only a name. It leans on
   --axis like everything else — the crossing here is between the two planes, not
   against the page, so the beam remains this page's one crossing diagonal (rule 2). */
.stand {
    position: relative;
    z-index: 1;
    margin: 12px 0 0 -16px;
    transform: rotate(var(--axis));
    transform-origin: 0 100%;
    user-select: none;
}

.stand-word {
    display: block;
    font-family: var(--agitprop);
    font-weight: 900;
    text-transform: uppercase;
    line-height: 0.86;
    color: var(--ink);
    margin: 0;
}

/* front plane: the site's own .extrude, whose side-face falls down-right */
.stand-word--front {
    position: relative;
    z-index: 1;
    font-size: clamp(74px, 25vw, 112px);
}

/* rear plane: mounted lower on the stand, so its face is seen from underneath and
   the extrusion throws UP. The side is the page's accent — a solid block of colour
   forming a letter's edge is area, not tinted type. */
.stand-word--rear {
    position: relative;
    z-index: 0;
    font-size: clamp(42px, 14vw, 62px);
    /* set just clear of the front word's baseline and offset right of it: the two
       planes meet where the accent side-face rises behind the front letters, which is
       the crossing. Any further up and the front word simply covers this one. */
    margin: -8px 0 0 26px;
    text-shadow:
        1px -1px 0 var(--accent),  2px -2px 0 var(--accent),  3px -3px 0 var(--accent),
        4px -4px 0 var(--accent),  5px -5px 0 var(--accent),  6px -6px 0 var(--accent),
        7px -7px 0 var(--accent);
}

/* --- chat --------------------------------------------------------------- */

/* The chat does not wear the masthead module. It gets the one device the rest of
   the site only ever hints at: a real corner-to-corner diagonal that other elements
   are positioned against rather than decorated with. The band enters at one page
   edge and leaves at the other, the wordmark is set INSIDE it (so the type is in the
   picture, not on it), and the fist passes behind it. */
.wire-head {
    position: relative;
    overflow: hidden;
    min-height: 232px;
    box-sizing: border-box;
}

/* Wider than the viewport by design so both ends are cropped by the page edge. It
   crosses the site axis instead of sharing it — see rule 2: one axis for everything
   that holds content, at most one crossing diagonal per page, and it is never a panel. */
.wire-band {
    position: absolute;
    left: -24%;
    width: 148%;
    top: 78px;
    height: 76px;
    background: var(--ink);
    transform: rotate(13deg);
    z-index: 2;
    display: flex;
    align-items: center;
    /* pushes the type back off the band's overhanging left end to roughly the
       viewport's own left edge */
    padding-left: 27%;
    box-sizing: border-box;
}

.wire-mark {
    margin: 0;
    color: var(--paper);
    font-size: 40px;
    line-height: 1;
    white-space: nowrap;
}

/* the same band again at a fraction of the depth — repetition at shrinking scale,
   carrying the page's accent so the blue is spent as area */
.wire-band--echo {
    top: 186px;
    height: 13px;
    background: var(--accent);
    padding: 0;
    z-index: 1;
}

/* Bottom LEFT, not bottom right: the bands rise to the left, so that corner is the
   only clear paper in the header. On the right the kicker lands on the accent band,
   and --ink on --blue is 2.01:1. */
.wire-kicker {
    position: absolute;
    left: 20px;
    bottom: 14px;
    z-index: 3;
    margin: 0;
}

/* fist.svg used to sit here and no longer does. It is --ink and so is the band, so
   at any position that fits inside a 232px header their masses weld into one
   unreadable lump — and rule 5 is explicit that a motif which can be removed without
   moving anything else is decoration. The band is this page's fragment; it does the
   structural work the fist was only gesturing at. */

.centralised {
    max-width: 640px;
    margin: 0 auto;
    padding: 20px 20px 60px;
}

.chathistory {
    max-height: 58vh;
    overflow-y: auto;
    margin: 0 0 22px;
    padding: 22px 20px;
    text-align: left;
    font-family: var(--body-serif);
    font-size: 15px;
    line-height: 1.5;
}

/* --- the wire slip ---
   The log is the most-used surface on the site and used to be the least designed one:
   `[user]: message` with a thin rule between, which is the plain bracketed list every
   other page on the site invented a device to avoid. A message is now two fragments in
   the site's own grammar — a hard block of colour with the name set in agitprop caps
   beside it, and the text in the body serif underneath. Name and message differ by
   face, weight, scale and colour-as-area, the same four moves the post header uses one
   scale up. The block is the page's accent on the session's own messages and --ink on
   everyone else's; the accent never touches the name itself (rule 4). */

.wire-msg { margin: 0 0 18px; }
.wire-msg:last-child { margin-bottom: 0; }

/* a run from one author states the name once and closes up under it */
.wire-msg--cont { margin-top: -10px; }

.wire-from {
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--agitprop);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink);
    margin: 0 0 5px;
}

.wire-tick {
    flex: none;
    width: 20px;
    height: 7px;
    background: var(--ink);
}

.wire-msg--own .wire-tick { background: var(--accent); }

.wire-text {
    margin: 0;
    font-family: var(--body-serif);
    font-size: 15px;
    line-height: 1.5;
}

/* The compose box is a paper fragment laid on a darker sheet, exactly as on the
   login panel. Without the darker backing the textarea is --paper on a --paper page
   and the only thing separating them is a 4px shadow — an input you cannot see. */
.chatbox {
    position: relative;
    padding: 20px 18px 18px;
}

.chatbox .txtarea {
    height: 64px;
    font-size: 16px;
    resize: none;
    margin-bottom: 16px;
}

/* The most-used surface on the site gets the same cut-paper affordance as every
   other primary action. Enter still sends; the button is not a fallback for it. */
.transmit-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.transmit-note {
    font-family: var(--agitprop);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    margin: 0;
    color: var(--ink);
}

/* --- colophon ------------------------------------------------------------
   Technical-drawing register: giant section numerals, hard leader lines running
   from a specimen to its label, and pins set on a live panel that annotates
   itself. New vocabulary, same materials — no soft edges, everything on --axis. */

.spec-wrap {
    position: relative;
    max-width: 640px;
    margin: 0 auto;
    padding: 30px 20px 90px;
}

.spec {
    position: relative;
    margin: 0 0 74px;
    padding-top: 10px;
}

/* the numeral is a montage fragment in its own right: oversized, on-axis, and
   overlapped by the heading that names it */
.spec-index {
    position: absolute;
    left: -6px;
    top: -6px;
    z-index: 0;
    font-size: 96px;
    line-height: 1;
    color: var(--gray);
    opacity: 0.42;
    transform: rotate(var(--axis));
    transform-origin: 0 50%;
    user-select: none;
}

.spec-head {
    position: relative;
    z-index: 1;
    font-size: 27px;
    margin: 0 0 12px 20px;
}

.spec-lede {
    position: relative;
    z-index: 1;
    font-size: 15px;
    line-height: 1.6;
    margin: 0 0 14px;
    max-width: 46ch;
}

.spec-lede code {
    font-family: var(--agitprop);
    font-size: 13px;
    background: var(--paper-dark);
    padding: 1px 5px;
}

/* ink type, accent rule — the same accent-as-area rule as .byline. --red on paper
   is 4.19:1, which misses AA for anything under 18px. */
.spec-lede a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 3px solid var(--accent);
}

/* the leader: a hard 2px rule that grows to fill whatever gap is left between a
   specimen and its label, so the two always stay tied together */
.lead {
    flex: 1 1 16px;
    min-width: 12px;
    align-self: center;
    border-top: 2px solid var(--ink);
    opacity: 0.4;
}

/* --- palette strip --- */

.swatch-strip { margin-top: 22px; }

.swatch-row {
    display: flex;
    align-items: stretch;
    gap: 10px;
    margin: 0 0 12px;
}

/* chips step down in width across the strip — the same shrinking-scale device the
   rest of the site uses, doing real work here as a reading order */
.swatch {
    flex: none;
    height: 44px;
    box-shadow: 5px 5px 0 rgba(28,26,23,0.8);
    clip-path: polygon(0 3px, 5px 0, calc(100% - 4px) 2px, 100% 0,
                       calc(100% - 2px) calc(100% - 4px), calc(100% - 7px) 100%,
                       4px calc(100% - 2px), 0 100%);
}

.swatch-label {
    flex: none;
    width: 168px;
    align-self: center;
}

.swatch-label b {
    display: block;
    font-size: 14px;
    letter-spacing: 0.02em;
}

.swatch-var,
.swatch-note {
    display: block;
    font-family: var(--agitprop);
    font-size: 10px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.swatch-note {
    font-family: var(--body-serif);
    font-size: 12px;
    letter-spacing: 0;
    text-transform: none;
    margin-top: 2px;
}

/* --- the self-documenting panel --- */

.exploded {
    position: relative;
    margin: 30px 0 30px;
    padding: 12px 32px 20px 26px;
}

.exploded-panel { padding: 34px 24px 38px; }

/* solid, not a 28%-opacity watermark: the section's claim is that this is a real
   panel rather than a picture of one, and a ghosted label undercuts it */
.exploded-word {
    font-size: 26px;
    margin: 0;
    color: var(--ink);
}

/* pins sit ON the thing they name — the panel annotates itself rather than
   sitting next to a picture of itself */
.pin {
    position: absolute;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent);
    color: var(--paper);
    font-family: var(--agitprop);
    font-weight: 900;
    font-size: 12px;
    box-shadow: 3px 3px 0 rgba(28,26,23,0.8);
    clip-path: polygon(0 3px, 4px 0, calc(100% - 3px) 1px, 100% 5px,
                       calc(100% - 2px) 100%, 3px calc(100% - 2px), 0 calc(100% - 5px));
}

.pin--tear   { top: 0;     right: 46px; }
.pin--shadow { bottom: 0;  right: 2px; }
.pin--tilt   { top: 52%;   left: 0; }

.callouts { margin: 0; }

.callout {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 0 0 12px;
}

.callout-num {
    flex: none;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--ink);
    color: var(--paper);
    font-family: var(--agitprop);
    font-weight: 900;
    font-size: 11px;
    align-self: flex-start;
    clip-path: polygon(0 3px, 4px 0, calc(100% - 3px) 1px, 100% 5px,
                       calc(100% - 2px) 100%, 3px calc(100% - 2px), 0 calc(100% - 5px));
}

.callout .lead {
    flex: none;
    width: 14px;
    align-self: flex-start;
    margin-top: 10px;
}

.callout-text {
    flex: 1;
    font-size: 14px;
    line-height: 1.55;
}

.callout-text code {
    font-family: var(--agitprop);
    font-size: 12px;
    background: var(--paper-dark);
    padding: 1px 4px;
}

/* --- type specimen --- */

.specimen {
    margin: 0 0 18px;
    padding: 18px 20px 16px;
    background: var(--paper-dark);
    box-shadow: 7px 7px 0 rgba(28,26,23,0.85);
}

.specimen--agit  { clip-path: polygon(0 5px, 7px 0, calc(100% - 9px) 3px, 100% 0,
                                      calc(100% - 3px) calc(100% - 7px), calc(100% - 11px) 100%,
                                      6px calc(100% - 4px), 0 100%); }
.specimen--serif { clip-path: polygon(4px 0, 100% 4px, calc(100% - 5px) calc(100% - 3px),
                                      calc(100% - 12px) calc(100% - 8px), 8px 100%, 0 calc(100% - 9px)); }

.specimen-glyphs {
    margin: 0 0 8px;
    font-size: 34px;
    line-height: 1.1;
}
.specimen--agit .specimen-glyphs { letter-spacing: -0.01em; }
.specimen--serif .specimen-glyphs { font-size: 32px; }

.specimen-spec {
    margin: 0;
    font-family: var(--agitprop);
    font-size: 10px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.7;
}

/* --- the punched card ---
   The one appropriated object on the site: every other fragment is a shape drawn for
   this project, and this is a found artifact reproduced faithfully and re-charged by
   what is punched into it. It earns its place in the technical-drawing register the
   same way the title block does — a card is a manufactured object with a printed grid,
   so it is ruled rather than torn, except for the corner, which really is a cut.
   Positions are gray hairlines and punches are filled ink slots: the two differ by
   SCALE, not by a tint of the same colour. */

.card {
    position: relative;
    margin: 26px 0 14px;
    /* right padding clears the 20px corner cut, per rule 3's per-edge invariant */
    padding: 15px 26px 17px 15px;
    background: var(--paper-dark);
    box-shadow: 8px 8px 0 rgba(28,26,23,0.85);
    transform: rotate(var(--axis-soft));
    clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
}

/* printed one character per column, on the same track as the grid below it, so each
   letter stands directly over the holes that encode it — which is how the machine
   printed it and what makes the correspondence legible */
.card-print {
    display: grid;
    column-gap: 1px;
    margin: 0 0 11px;
    font-size: 9px;
    letter-spacing: 0;
    text-align: center;
    color: var(--ink);
}

.card-grid {
    display: grid;
    grid-auto-rows: 7px;
    align-items: center;
    column-gap: 1px;
    row-gap: 3px;
}

.card-pos {
    height: 2px;
    background: var(--gray);
}

.card-pos.is-punched {
    height: 7px;
    background: var(--ink);
}

.card-cap {
    margin: 0 0 4px;
    font-size: 13px;
    line-height: 1.55;
    max-width: 44ch;
}

/* --- spec list --- */

.spec-list { margin: 22px 0 0; }

.spec-row {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 10px 0 9px;
    border-bottom: 2px solid var(--ink);
}
.spec-row:first-child { border-top: 2px solid var(--ink); }

.spec-row dt {
    flex: none;
    width: 92px;
    font-size: 12px;
    letter-spacing: 0.1em;
}

.spec-row dd {
    flex: 1;
    margin: 0;
    font-size: 14px;
}

/* --- drawing title block ---
   The colophon's header, and the most characteristic object in the register it
   already works in. A title block is DRAWN, not cut: hard ruled borders and square
   cells, which is why it is the one rectangle on the site — rule 3 governs cut paper,
   and this is the drafting instrument, not a fragment of it. */

.titleblock {
    position: relative;
    margin: 26px 18px 0;
    border: 3px solid var(--ink);
    background: var(--paper);
    transform: rotate(var(--axis-soft));
    overflow: hidden;
}

.tb-main {
    position: relative;
    z-index: 1;
    padding: 16px 18px 14px;
    border-bottom: 3px solid var(--ink);
}

.tb-main .kicker { margin: 0 0 10px; }

.tb-title {
    font-size: clamp(34px, 11vw, 54px);
    line-height: 0.94;
    margin: 0;
}

.tb-cells {
    position: relative;
    z-index: 1;
    display: flex;
}

.tb-cell {
    flex: 1;
    padding: 8px 10px 9px;
    border-right: 3px solid var(--ink);
}
.tb-cell:last-child { border-right: none; }

.tb-cell b,
.tb-cell span {
    display: block;
    font-family: var(--agitprop);
    text-transform: uppercase;
}

.tb-cell b {
    font-size: 9px;
    letter-spacing: 0.16em;
    color: var(--gray);
    margin-bottom: 3px;
}

.tb-cell span {
    font-size: 14px;
    font-weight: 900;
    letter-spacing: 0.02em;
}

/* cropped by the block's own ruled border, with the title running across it */
.tb-mark {
    position: absolute;
    right: -30px;
    top: -26px;
    width: 92px;
    transform: rotate(var(--axis-hard));
    z-index: 0;
}
