/* ============================================================================
   components.css — the parts the page is assembled from.

   One rule governs the whole file: the decor is drawn, the content is not.
   Anything a visitor has to read sits on a .plate — a flat recessed panel with
   a single hairline frame and four bronze register ticks at the corners, and
   nothing else. No texture, no gradient, no drop shadow. The drawings, gears,
   compass and lamp live outside the panels, at the edges and in the transitions.
   ========================================================================= */

/* ────────────────────────────────────────────────────────────────────────────
   PLATE — the one content surface.

   A cut sheet on the drafting ground: 1px frame, faintly darker fill, and the
   register marks a plate is cropped to. The marks are eight gradients on one
   pseudo-element, so a plate needs no extra markup to be framed.

   The named containers below are plates too — the passport, the skills rail,
   the terminal strip, the ledger and the filter bar. Listing them here is what
   keeps them from having to say so in the markup.
   ──────────────────────────────────────────────────────────────────────────── */
.plate,
.passport,
.rail,
.terminal,
.worklist-wrap,
.filterbar {
  position: relative;
  border: 1px solid var(--c-rule);
  border-radius: var(--r-panel);
  background-color: var(--c-panel);
  transition: border-color var(--t-mid) var(--ease-mech),
              background-color var(--t-mid) var(--ease-mech);
}

.plate::before,
.passport::before,
.rail::before,
.terminal::before,
.worklist-wrap::before,
.filterbar::before {
  content: "";
  position: absolute;
  inset: -1px;                       /* land the marks on the frame itself */
  z-index: 2;
  pointer-events: none;
  background-image:
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c)),
    linear-gradient(var(--tick-c), var(--tick-c));
  background-repeat: no-repeat;
  background-size:
    var(--tick-len) var(--tick-w), var(--tick-w) var(--tick-len),
    var(--tick-len) var(--tick-w), var(--tick-w) var(--tick-len),
    var(--tick-len) var(--tick-w), var(--tick-w) var(--tick-len),
    var(--tick-len) var(--tick-w), var(--tick-w) var(--tick-len);
  background-position:
    left top, left top,
    right top, right top,
    left bottom, left bottom,
    right bottom, right bottom;
  transition: background-image var(--t-mid) var(--ease-mech);
}

.plate--pad { padding: clamp(var(--sp-5), 2.4vw, var(--sp-6)); }

/* Head: the running head of a drawing — sheet number on the left, state on
   the right, a hairline under both. */
.plate__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) clamp(var(--sp-4), 2vw, var(--sp-5)) var(--sp-3);
  border-bottom: 1px solid var(--c-rule);
}

.plate__title {
  margin-top: var(--sp-4);
  padding-inline: clamp(var(--sp-4), 2vw, var(--sp-5));
  font-size: var(--fs-h3);
  font-weight: 600;
}

.plate__body {
  flex: 1 1 auto;                    /* absorb the slack: uneven copy lengths
                                        must not leave the tag rows ragged */
  padding: var(--sp-3) clamp(var(--sp-4), 2vw, var(--sp-5)) var(--sp-4);
  color: var(--fg-dim);
}

/* The tag row rides at the foot of the body, above the ruled foot. */
.plate > .tags {
  margin-top: var(--sp-4);
  padding-inline: clamp(var(--sp-4), 2vw, var(--sp-5));
}

.plate__foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  margin-top: auto;
  padding: var(--sp-3) clamp(var(--sp-4), 2vw, var(--sp-5)) var(--sp-4);
  border-top: 1px solid var(--c-rule);
}

/* A plate that is itself a link. It lifts a little and its frame warms up —
   no rotation, no shadow theatre. */
.plate { display: flex; flex-direction: column; }

.plate--link {
  color: inherit;
  text-decoration: none;
  transition: border-color var(--t-mid) var(--ease-mech),
              background-color var(--t-mid) var(--ease-mech),
              transform var(--t-mid) var(--ease-out);
}

.plate--link:hover,
.plate--link:focus-visible {
  transform: translateY(-3px);
  border-color: var(--c-rule-brass);
  background-color: var(--c-panel-hi);
  box-shadow: var(--sh-lift);
}

.plate--link:hover::before,
.plate--link:focus-visible::before { --tick-c: var(--c-brass-lt); }

/* The lead card spans the sheet, so its interior has to use that width rather
   than stretch one paragraph across it: the copy keeps a reading measure and the
   tag row comes up alongside instead of sitting underneath. Same plate, same
   frame, same ticks — only the arrangement changes. */
@media (min-width: 62.001rem) {
  .plate--feature {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    align-items: start;
  }
  .plate--feature > .plate__head,
  .plate--feature > .plate__foot { grid-column: 1 / -1; }
  .plate--feature > .plate__title,
  .plate--feature > .plate__body { grid-column: 1; }
  .plate--feature > .tags {
    grid-column: 2;
    grid-row: 2 / span 2;
    align-content: start;
    margin-top: var(--sp-5);
  }
  .plate--feature > .plate__foot { margin-top: 0; }
}

.plate__go {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
  color: var(--c-amber);
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

.plate__go svg {
  width: 1em; height: 1em;
  stroke: currentColor; fill: none; stroke-width: 1.7;
  transition: transform var(--t-mid) var(--ease-out);
}
.plate--link:hover .plate__go svg { transform: translateX(4px); }

/* ────────────────────────────────────────────────────────────────────────────
   BUTTONS — controls, so they are the most material thing on the page: a solid
   fill or a plain outline, one radius, no metal gradients.
   ──────────────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.66em 1.15em;
  border: 1px solid var(--c-rule-hi);
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--fg);
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease-mech),
              border-color var(--t-fast) var(--ease-mech),
              color var(--t-fast) var(--ease-mech),
              transform var(--t-fast) var(--ease-mech);
}

.btn:hover { border-color: var(--c-rule-brass); background: var(--c-panel-hi); }
.btn:active { transform: translateY(1px); }

.btn__icon {
  width: 1.05em; height: 1.05em;
  stroke: currentColor; fill: none; stroke-width: 1.7;
  transition: transform var(--t-mid) var(--ease-out);
}
.btn:hover .btn__icon { transform: translateX(3px); }

/* The one filled button on any given screen. It is filled with the mark
   material rather than the line material: the brass draws, the mark decides. */
.btn--fill {
  border-color: var(--c-mark);
  background: var(--c-mark);
  color: var(--c-on-mark);
}
.btn--fill:hover {
  border-color: var(--c-mark);
  background: color-mix(in srgb, var(--c-mark) 84%, var(--c-fg));
  color: var(--c-on-mark);
}

/* Secondary. `--ink` and `--onDark` were two different surfaces once; with a
   single ground they are the same control, kept as aliases so the markup that
   already names them keeps working. */
.btn--ink,
.btn--onDark,
.btn--ghost {
  border-color: var(--c-rule-hi);
  background: transparent;
  color: var(--fg);
}
.btn--ink:hover,
.btn--onDark:hover,
.btn--ghost:hover {
  border-color: var(--c-brass);
  background: color-mix(in srgb, var(--c-brass) 12%, transparent);
  color: var(--c-fg);
}

.btn--sm { padding: 0.5em 0.95em; font-size: var(--fs-xs); }

/* Bare. Three boxes of equal weight make all three look optional, so the routes
   that are not the point lose the box and keep the voice. */
.btn--bare {
  padding-inline: 0;
  border-color: transparent;
  background: transparent;
  color: var(--fg-dim);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.4em;
  transition: color var(--t-fast) var(--ease-mech),
              text-decoration-color var(--t-fast) var(--ease-mech);
}
.btn--bare:hover {
  border-color: transparent;
  background: transparent;
  color: var(--link);
  text-decoration-color: currentColor;
}
.btn--bare:active { transform: none; }

/* ────────────────────────────────────────────────────────────────────────────
   PASSPORT — the engineer's particulars, set out like a title block.
   ──────────────────────────────────────────────────────────────────────────── */
.passport { padding: var(--sp-5) clamp(var(--sp-4), 2.2vw, var(--sp-5)); }

.passport__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--c-rule);
}

.passport__body { padding-top: var(--sp-4); }

.passport__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-rule);
}

/* ── Spec rows: key on the left, value on the right, ruled between. ───────── */
.spec { display: grid; }

.spec__row {
  display: grid;
  grid-template-columns: minmax(6.5rem, 34%) 1fr;
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
  border-bottom: 1px dashed var(--c-rule);
}
.spec__row:last-child { border-bottom: 0; }

.spec__key {
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}

.spec__val { color: var(--fg); font-size: var(--fs-sm); }
.spec__val--accent { color: var(--c-brass-lt); font-weight: 600; }

/* ────────────────────────────────────────────────────────────────────────────
   STATUS — a lamp and a word.
   ──────────────────────────────────────────────────────────────────────────── */
.status {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  white-space: nowrap;
}

.status::before {
  content: "";
  width: 7px; height: 7px;
  flex: none;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent);
}

.status--live { color: var(--c-st-live); }
.status--live::before { animation: breathe 3.4s var(--ease-mech) infinite; }
.status--wip  { color: var(--c-st-wip); }
.status--wip::before  { animation: blink 2.6s steps(1, end) infinite; }
.status--hold { color: var(--c-st-hold); }
.status--arch { color: var(--c-st-arch); }

@keyframes breathe {
  0%, 100% { opacity: 1;   box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent); }
  50%      { opacity: 0.7; box-shadow: 0 0 0 6px color-mix(in srgb, currentColor 5%,  transparent); }
}
@keyframes blink { 0%, 62% { opacity: 1; } 63%, 100% { opacity: 0.3; } }

/* ────────────────────────────────────────────────────────────────────────────
   TAGS — stack, flat.
   ──────────────────────────────────────────────────────────────────────────── */
.tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.tag {
  display: inline-block;
  padding: 0.24em 0.62em;
  border: 1px solid var(--c-rule);
  border-radius: var(--r-ctl);
  background: var(--c-well);
  color: var(--fg-dim);
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-mono);
  white-space: nowrap;
}

.tag--brass {
  border-color: var(--c-rule-brass);
  color: var(--c-brass-lt);
}

.tag--ink {
  border-color: var(--c-rule-hi);
  color: var(--fg);
}

/* ────────────────────────────────────────────────────────────────────────────
   RAIL — the skills panel. A DIN rail with modules clipped onto it: each row
   is one module, its icon the machine part it stands for.
   ──────────────────────────────────────────────────────────────────────────── */
.rail { padding: var(--sp-5) clamp(var(--sp-4), 2.2vw, var(--sp-5)) var(--sp-4); }

.rail__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-bottom: var(--sp-3);
}

.rail__count {
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}

/* The rail itself: a bronze section with mounting slots punched along it. */
.rail__bar {
  position: relative;
  height: 7px;
  margin-bottom: var(--sp-2);
  border-radius: 1px;
  background: linear-gradient(180deg,
      var(--c-brass-lt) 0 1px,
      var(--c-brass) 1px 46%,
      var(--c-brass-dk) 46% 100%);
}

.rail__bar::after {
  content: "";
  position: absolute;
  inset: 2px 12px;
  background: repeating-linear-gradient(90deg,
      rgba(20, 14, 6, 0.55) 0 5px, transparent 5px 18px);
}

.rail__mods { display: grid; }

.mod {
  position: relative;
  display: grid;
  grid-template-columns: 2.4rem 1fr auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-2);
  border-bottom: 1px solid var(--c-rule);
  transition: background-color var(--t-fast) var(--ease-mech);
}
.mod:last-child { border-bottom: 0; }
.mod:hover { background: color-mix(in srgb, var(--c-brass) 7%, transparent); }

/* the stub that clips the module to the rail */
.mod::before {
  content: "";
  position: absolute;
  top: -1px; left: 1.05rem;
  width: 2px; height: var(--sp-3);
  background: var(--c-brass-dk);
}

.mod__part {
  width: 2.4rem; height: 2.4rem;
  padding: 0.32rem;
  border: 1px solid var(--c-rule);
  border-radius: var(--r-ctl);
  background: var(--c-well);
  stroke: var(--c-brass);
  fill: none;
  stroke-width: 1.5;
  transition: stroke var(--t-fast) var(--ease-mech),
              border-color var(--t-fast) var(--ease-mech);
}
.mod:hover .mod__part {
  stroke: var(--c-brass-lt);
  border-color: var(--c-rule-brass);
}

.mod__meta { display: flex; flex-direction: column; min-width: 0; }

.mod__name {
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--fg);
}

.mod__note {
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--fg-mute);
}

/* ────────────────────────────────────────────────────────────────────────────
   TERMINAL — contacts as a terminal strip. One row per way: screw, number,
   kind, value, wire.
   ──────────────────────────────────────────────────────────────────────────── */
.terminal { padding: var(--sp-4) clamp(var(--sp-4), 2.2vw, var(--sp-5)); }

.terminal__row {
  display: grid;
  grid-template-columns: auto 2.6rem 7.5rem 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-2);
  border-bottom: 1px solid var(--c-rule);
  transition: background-color var(--t-fast) var(--ease-mech);
}
.terminal__row:last-child { border-bottom: 0; }
.terminal__row:hover { background: color-mix(in srgb, var(--c-brass) 7%, transparent); }

/* the clamping screw — turns a little when you reach for the row */
.terminal__screw {
  position: relative;
  width: 15px; height: 15px;
  flex: none;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 32%,
      var(--c-brass-lt) 0 24%, var(--c-brass) 24% 60%, var(--c-brass-dk) 60% 100%);
  transition: transform var(--t-mid) var(--ease-mech);
}
.terminal__screw::before {
  content: "";
  position: absolute;
  inset: 46% 22%;
  border-radius: 1px;
  background: rgba(20, 14, 6, 0.72);
}
.terminal__row:hover .terminal__screw { transform: rotate(28deg); }

.terminal__id {
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  color: var(--fg-mute);
}

.terminal__kind {
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}

.terminal__val {
  min-width: 0;
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  color: var(--fg);
  overflow-wrap: anywhere;
  transition: color var(--t-fast) var(--ease-mech);
}
.terminal__row:hover .terminal__val { color: var(--c-brass-lt); }

/* the wire leaving the terminal */
.terminal__wire {
  width: clamp(1.5rem, 5vw, 3.2rem);
  height: 1px;
  background: linear-gradient(90deg, var(--c-rule-brass), transparent);
  transition: background var(--t-mid) var(--ease-mech);
}
.terminal__row:hover .terminal__wire {
  background: linear-gradient(90deg, var(--c-brass), transparent);
}

/* ────────────────────────────────────────────────────────────────────────────
   DECOR — drawn objects. None of it carries information, all of it is
   aria-hidden in the markup, and every piece is free to be elaborate.
   ──────────────────────────────────────────────────────────────────────────── */
.gear {
  position: absolute;
  opacity: var(--gear-op, 0.3);
  animation: spin var(--spin, 52s) linear infinite;
  pointer-events: none;
  user-select: none;
}
.gear--ccw { animation-direction: reverse; }
@keyframes spin { to { rotate: 1turn; } }

.compass {
  position: absolute;
  opacity: var(--compass-op, 0.22);
  pointer-events: none;
  user-select: none;
}

/* ── Marginal note, the way a reviser writes in the margin ────────────────── */
.note {
  padding-left: var(--sp-4);
  border-left: 2px solid color-mix(in srgb, var(--c-st-hold) 58%, transparent);
  color: var(--fg-dim);
  font-size: var(--fs-sm);
  font-style: italic;
}
.note strong { font-style: normal; font-weight: 600; color: var(--fg); }

/* A note that trails a whole block rather than sitting inside one, so it needs
   the gap that separates it from what it is commenting on. */
.note--detached { margin-top: var(--sp-7); }

/* ── Item balloon: the dossier number, ringed like a part on a drawing ───── */
.entry__no {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.15rem;
  aspect-ratio: 1;
  border: 1px solid var(--c-rule-brass);
  border-radius: var(--r-pill);
  background: var(--c-well);
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--c-mark-txt);
}

/* ────────────────────────────────────────────────────────────────────────────
   REVEAL — one short rise as a block enters. JS adds .is-in.
   ──────────────────────────────────────────────────────────────────────────── */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--t-slow) var(--ease-out),
              transform var(--t-slow) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* ────────────────────────────────────────────────────────────────────────────
   FILTER BAR — portfolio tag filter.
   ──────────────────────────────────────────────────────────────────────────── */
.filterbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-4);
  padding: var(--sp-4) clamp(var(--sp-4), 2vw, var(--sp-5));
}

.filterbar__chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.filterbar__readout {
  margin-left: auto;
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  color: var(--fg-mute);
  white-space: nowrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.36em 0.78em;
  border: 1px solid var(--c-rule);
  border-radius: var(--r-ctl);
  background: var(--c-well);
  color: var(--fg-dim);
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-mono);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-mech),
              background-color var(--t-fast) var(--ease-mech),
              color var(--t-fast) var(--ease-mech);
}
.chip:hover { border-color: var(--c-rule-brass); color: var(--fg); }

.chip[aria-pressed="true"] {
  border-color: var(--c-mark);
  background: var(--c-mark);
  color: var(--c-on-mark);
}

.chip__n { font-weight: 400; opacity: 0.68; }
.chip__n:empty { display: none; }

/* ────────────────────────────────────────────────────────────────────────────
   WORKLIST — the recruiter's ledger. A table, ruled, nothing more.
   ──────────────────────────────────────────────────────────────────────────── */
.worklist-wrap { padding: var(--sp-2) clamp(var(--sp-3), 2vw, var(--sp-4)) var(--sp-4); overflow-x: auto; }

/* The ledger is the one plate that scrolls, and `overflow-x: auto` makes
   `overflow-y` compute to auto with it. That turns the panel into a scroll
   container, where the register marks' 1px overhang counts as scrollable
   overflow and raises a scrollbar on a table that fits. Pull the marks just
   inside the frame here — at 1px the difference is not visible, and the
   phantom scrollbar goes away. */
.worklist-wrap::before { inset: 0; }

.worklist { font-size: var(--fs-sm); }

.worklist thead th {
  padding: var(--sp-3);
  border-bottom: 1px solid var(--c-rule-hi);
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
  color: var(--fg-mute);
}

.worklist tbody tr {
  border-bottom: 1px solid var(--c-rule);
  transition: background-color var(--t-fast) var(--ease-mech);
}
.worklist tbody tr:nth-child(even) { background: color-mix(in srgb, var(--c-well) 60%, transparent); }
.worklist tbody tr:hover { background: color-mix(in srgb, var(--c-brass) 8%, transparent); }

.worklist td { padding: var(--sp-3); vertical-align: top; color: var(--fg-dim); }

.worklist__name {
  font-family: var(--ff-mono);
  font-weight: 600;
  color: var(--fg);
  text-decoration: none;
}
.worklist__name:hover { color: var(--c-amber-hi); text-decoration: underline; }

.worklist__note {
  display: block;
  margin-top: 0.2em;
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  color: var(--fg-mute);
}

.worklist__year {
  font-family: var(--ff-mono);
  font-variant-numeric: tabular-nums;
  color: var(--fg-mute);
  white-space: nowrap;
}

.worklist__links { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.worklist__empty {
  padding: var(--sp-7) var(--sp-4);
  text-align: center;
  color: var(--fg-mute);
  font-family: var(--ff-mono);
  font-size: var(--fs-sm);
}

/* Narrow screens: the ledger unpacks into one record per row, each cell
   labelled from its column header.

   Each cell rules its own two columns rather than borrowing the row's with
   subgrid. Subgrid looks tidier on paper, but it auto-places every child of a
   cell into the shared grid, so the moment a cell holds two things — a project
   name and its note — the second one lands under the label instead of beside
   it. The labels line up anyway: they all fit inside the same fixed floor. */
@media (max-width: 52rem) {
  .worklist thead { display: none; }

  .worklist tbody tr { display: block; padding: var(--sp-3) 0; }

  .worklist td {
    display: grid;
    /* 4.75rem clears the longest header, PROJECT, and no more: every pixel the
       label column does not take is a pixel the value gets on a 360px phone. */
    grid-template-columns: minmax(4.75rem, max-content) 1fr;
    gap: 0 var(--sp-3);
    align-items: baseline;
    padding: var(--sp-1) var(--sp-2);
  }

  .worklist td::before {
    content: attr(data-col);
    grid-column: 1;
    font-family: var(--ff-mono);
    font-size: var(--fs-label);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--fg-mute);
  }

  /* Everything the cell actually holds stacks in the second column. */
  .worklist td > * { grid-column: 2; }

  /* A dotted namespace like CmlLib.Core.Installer.NeoForge is a single word to
     the line breaker, and the value track's floor is its widest word — so on a
     narrow phone that one entry drags the whole ledger sideways. Let it break
     mid-word here; on the desktop table there is room and it never triggers. */
  .worklist__name { overflow-wrap: anywhere; }
}

/* ────────────────────────────────────────────────────────────────────────────
   ENTRY — a project dossier: copy on one side, screenshot on the other.
   ──────────────────────────────────────────────────────────────────────────── */
.entry {
  display: grid;
  grid-template-columns: 1fr minmax(0, 0.82fr);
  gap: clamp(var(--sp-5), 3vw, var(--sp-7));
  padding: clamp(var(--sp-5), 2.6vw, var(--sp-7));
}

.entry--flip { grid-template-columns: minmax(0, 0.82fr) 1fr; }
.entry--flip .entry__main { order: 2; }
.entry--flip .entry__shot { order: 1; }

/* Not every dossier earns a picture. One column, capped to a reading measure so
   the copy does not run the full width of the sheet. */
.entry--solo { grid-template-columns: minmax(0, 72ch); }

.entry__main { min-width: 0; }

.entry__title {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.entry__name {
  font-size: var(--fs-h3);
  font-weight: 600;
}

.entry__shot { min-width: 0; }

.entry__links { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-5); }

.entry__sub {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--c-rule);
}

.entry__sub li { font-size: var(--fs-sm); color: var(--fg-dim); }
.entry__sub b {
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-mono);
  color: var(--fg);
}

@media (max-width: 56rem) {
  .entry, .entry--flip { grid-template-columns: 1fr; }
  .entry--flip .entry__main { order: 1; }
  .entry--flip .entry__shot { order: 2; }
}

/* ── Screenshot well. Empty ones read as an unfinished view on a drawing. ─── */
.shot {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--c-rule);
  border-radius: var(--r-panel);
  background: var(--c-well);
}

.shot img { width: 100%; height: 100%; object-fit: cover; }

.shot--empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(45deg,
      var(--c-rule) 0 1px, transparent 1px 11px);
  opacity: 0.7;
}

.shot--empty::after {
  content: "";
  position: absolute;
  inset: var(--sp-3);
  border: 1px dashed var(--c-rule-hi);
  border-radius: 1px;
}

.shot__note {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  padding: var(--sp-2) var(--sp-3);
  background: color-mix(in srgb, var(--c-void) 78%, transparent);
  color: var(--fg-mute);
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  text-align: center;
}

/* ────────────────────────────────────────────────────────────────────────────
   PROSE — running text.
   ──────────────────────────────────────────────────────────────────────────── */
.prose { max-width: 68ch; }
.prose > * + * { margin-top: var(--sp-4); }
.prose p { color: var(--fg-dim); }

/* ── The contacts panel carries one drawn coil in its bottom corner ───────── */
.contact__aside { position: relative; align-self: start; overflow: hidden; }

.contact__coil {
  position: absolute;
  right: -1.6rem;
  bottom: -1.8rem;
  width: clamp(6rem, 11vw, 9.5rem);
  opacity: 0.16;
  pointer-events: none;
}

/* ────────────────────────────────────────────────────────────────────────────
   MEASURE MODE — the page annotating itself, on M. Invisible until then, and
   it costs an ordinary visitor nothing: measure.js builds the overlay the
   first time the key is pressed and empties it again on the way out.

   The dimensions are drawn the way they are on the hero sheet: brass hairline,
   ticks at both ends, and the figure knocked out of the line rather than
   sitting beside it. Same tokens, so a palette change carries through here too.
   ──────────────────────────────────────────────────────────────────────────── */
:root.is-measuring {
  /* The drafting grid is always there at 4.5%. Here it comes up to where it can
     actually be read against, which is the point of a measured drawing. */
  --c-grid:    color-mix(in srgb, var(--c-brass) 10%, transparent);
  --c-grid-hi: color-mix(in srgb, var(--c-brass) 19%, transparent);
}

.measure {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 0;                       /* children carry their own document coords */
  z-index: 60;
  pointer-events: none;
  font-family: var(--ff-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-brass-lt);
}

.measure__dim { position: absolute; }

.measure__dim::before,
.measure__dim::after {
  content: "";
  position: absolute;
  background: var(--tick-c);
  opacity: 0.75;
}

.measure__val {
  position: absolute;
  padding: 0 0.45em;
  background: var(--c-ground);     /* the knockout: the line stops at the figure */
  white-space: nowrap;
}

/* ── Horizontal: the content measure ──────────────────────────────────────── */
.measure__dim--h {
  height: 0;
  border-top: 1px solid var(--c-rule-brass);
}

.measure__dim--h::before,
.measure__dim--h::after {
  top: calc(var(--tick-len) / -2);
  width: 1px;
  height: var(--tick-len);
}

.measure__dim--h::before { left: 0; }
.measure__dim--h::after  { right: 0; }

.measure__dim--h .measure__val {
  left: 50%;
  bottom: 0.35em;
  transform: translateX(-50%);
}

/* ── Vertical: one per section, standing in the left margin ───────────────── */
.measure__dim--v {
  width: 0;
  border-left: 1px solid var(--c-rule-brass);
}

.measure__dim--v::before,
.measure__dim--v::after {
  left: calc(var(--tick-len) / -2);
  width: var(--tick-len);
  height: 1px;
}

.measure__dim--v::before { top: 0; }
.measure__dim--v::after  { bottom: 0; }

.measure__dim--v .measure__val {
  top: 50%;
  left: 0.4em;
  padding: 0.45em 0;
  writing-mode: vertical-rl;
  transform: translateY(-50%) rotate(180deg);   /* reads upward, as on a sheet */
}

/* ── One leader, elbowed onto a shelf ─────────────────────────────────────── */
.measure__leader {
  position: absolute;
  overflow: visible;
}

.measure__leader path {
  fill: none;
  stroke: var(--c-rule-brass);
  stroke-width: 1;
}

.measure__tag {
  position: absolute;
  padding-bottom: 0.3em;
  color: var(--c-brass);
}

/* ── Corner readout: the figures that have no line to sit on ──────────────── */
/* Right-hand side: the vertical dimensions stand in the left margin, and the
   section indices sit under them. This is the corner with nothing in it. */
.measure__readout {
  position: fixed;
  right: var(--gutter);
  bottom: 1.1rem;
  padding: 0.55em 0.8em;
  border: 1px solid var(--c-rule-brass);
  background: var(--c-ground);
  color: var(--c-brass-lt);
}
