/* ==========================================================================
   Zion Rubin — project pages
   Loaded after home.css, which holds the tokens, the 12-column sheet (.obj),
   plates and diagram strokes. This adds the page head, the system map and its
   key, always-on figure labels, the one loop on the page, and the pager.
   Sections: head · sheets · figures · system map · key · loop · pager ·
             responsive
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Head
   A crumb line, then the name, one line, the deck and the contents. The
   contents sit on the right and end where the text ends.
   -------------------------------------------------------------------------- */

.crumbs {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-top: 24px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
}

.crumbs a { color: var(--ink-2); transition: color .3s var(--ease); }
.crumbs a:hover { color: var(--ink); }
.crumbs a:hover .arr { transform: translateX(-3px); }

.p-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  align-items: start;
  padding: clamp(56px, 10vh, 104px) 0 clamp(80px, 11vh, 128px);
}

.p-head .obj-meta { grid-column: 1 / span 6; grid-row: 1; }

.p-head h1 {
  grid-column: 1 / span 7;
  grid-row: 2;
  margin: 40px 0 0;
  font-size: clamp(2.25rem, 1.55rem + 2.9vw, 3.75rem);
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1;
}

.p-head .line {
  grid-column: 1 / span 6;
  grid-row: 3;
  max-width: 32ch;
  margin: 24px 0 0;
  color: var(--ink-2);
  font-size: clamp(1.125rem, 1rem + .55vw, 1.5rem);
  line-height: 1.4;
  letter-spacing: -.015em;
  text-wrap: pretty;
}

.p-deck, .p-note {
  grid-column: 1 / span 5;
  max-width: 48ch;
  color: var(--ink-2);
  font-size: 1rem;
  line-height: 1.6;
  text-wrap: pretty;
}

.p-deck { grid-row: 4; margin: 48px 0 0; }

.p-note {
  grid-row: 5;
  margin: 28px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.p-k {
  display: block;
  margin-bottom: 6px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.p-note a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .3s var(--ease);
}
.p-note a:hover { text-decoration-color: var(--ink); }

.p-index {
  grid-column: 9 / -1;
  grid-row: 3 / span 3;
  align-self: end;
}

.p-index ol {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
  list-style: none;
}

.p-index a {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 15px;
  transition: color .3s var(--ease);
}

.ix-n, .p-index .arr {
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  transition: color .3s var(--ease), transform .45s var(--ease);
}

.p-index .arr { opacity: 0; transition: opacity .3s var(--ease), transform .45s var(--ease); }
.p-index a:is(:hover, :focus-visible) { color: var(--ink); }
.p-index a:is(:hover, :focus-visible) .ix-n { color: var(--accent); }
.p-index a:is(:hover, :focus-visible) .arr { opacity: 1; transform: translateY(2px); }

/* --------------------------------------------------------------------------
   2. Sheets
   The homepage sheet, with a wider rail for longer text. Below 1100px
   home.css already gives the rail five columns.
   -------------------------------------------------------------------------- */

@media (min-width: 1100px) {
  .proj .obj-meta, .proj .obj-lead, .proj .obj-foot { grid-column: 1 / span 5; }
  .proj .plate { grid-column: 7 / -1; }
}

.p-text {
  max-width: 46ch;
  margin: 16px 0 0;
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1.6;
  text-wrap: pretty;
}

.p-text em { color: var(--ink); font-style: normal; }
.p-text code { color: var(--ink); font-family: var(--mono); font-size: .875em; }

.p-aside {
  margin: 20px 0 0;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   3. Figures
   On this page the drawings are the content, so labels are always shown,
   at a size that stays near 11px however wide the plate is drawn.
   -------------------------------------------------------------------------- */

.proj .d-lbl { opacity: 1; }
.proj .plate .d-lbl { font-size: 9.5px; }

.d-lbl .f-ink { fill: var(--ink); }
.d-lbl .f-act { fill: var(--accent); }

.f-on  { fill: var(--ink); }
.f-ac  { fill: var(--accent); }
.f-acs {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
.f-acb {
  fill: var(--plate);
  stroke: var(--accent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* --------------------------------------------------------------------------
   4. System map
   Sheet 00: the whole system on one drawing, full width, with a numbered key
   below it. The key and the drawing point at each other: hover or focus a
   key and the rest of the drawing steps back.
   -------------------------------------------------------------------------- */

.sys {
  position: relative;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: start;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  scroll-margin-top: 32px;
}

.sys .obj-meta { grid-column: 1 / span 4; grid-row: 1; }
.sys-lead { grid-column: 1 / span 5; grid-row: 2; min-width: 0; padding-top: 40px; }
.sys-spec { grid-column: 9 / -1; grid-row: 2; align-self: end; }

.sys-fig { grid-column: 1 / -1; grid-row: 3; min-width: 0; margin: 56px 0 0; }

.sys-fig figcaption {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 10px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 11px;
}
.sys-fig figcaption span:first-child { flex: none; }

.sys .d-lbl { font-size: 10.5px; }

.zone { transition: opacity .4s var(--ease); }

.co circle {
  fill: var(--plate);
  stroke: var(--dia);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  transition: fill .3s var(--ease), stroke .3s var(--ease);
}
.co text {
  fill: var(--ink-2);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  transition: fill .3s var(--ease);
}
.co { transform-box: fill-box; transform-origin: center; }

/* key → drawing */
.sys:has(.k1:is(:hover, :focus-visible)) .zone:not(.z1),
.sys:has(.k2:is(:hover, :focus-visible)) .zone:not(.z2),
.sys:has(.k3:is(:hover, :focus-visible)) .zone:not(.z3),
.sys:has(.k4:is(:hover, :focus-visible)) .zone:not(.z4),
.sys:has(.k5:is(:hover, :focus-visible)) .zone:not(.z5),
.sys:has(.k6:is(:hover, :focus-visible)) .zone:not(.z6),
.sys:has(.k7:is(:hover, :focus-visible)) .zone:not(.z7),
.sys:has(.zone[class*="z"]:not(.z0):hover) .zone:not(:hover) { opacity: .22; }

.sys:has(.k1:is(:hover, :focus-visible)) .z1 .co circle,
.sys:has(.k2:is(:hover, :focus-visible)) .z2 .co circle,
.sys:has(.k3:is(:hover, :focus-visible)) .z3 .co circle,
.sys:has(.k4:is(:hover, :focus-visible)) .z4 .co circle,
.sys:has(.k5:is(:hover, :focus-visible)) .z5 .co circle,
.sys:has(.k6:is(:hover, :focus-visible)) .z6 .co circle,
.sys:has(.k7:is(:hover, :focus-visible)) .z7 .co circle,
.zone:not(.z0):hover .co circle { fill: var(--accent); stroke: var(--accent); }

.sys:has(.k1:is(:hover, :focus-visible)) .z1 .co text,
.sys:has(.k2:is(:hover, :focus-visible)) .z2 .co text,
.sys:has(.k3:is(:hover, :focus-visible)) .z3 .co text,
.sys:has(.k4:is(:hover, :focus-visible)) .z4 .co text,
.sys:has(.k5:is(:hover, :focus-visible)) .z5 .co text,
.sys:has(.k6:is(:hover, :focus-visible)) .z6 .co text,
.sys:has(.k7:is(:hover, :focus-visible)) .z7 .co text,
.zone:not(.z0):hover .co text { fill: var(--bg); }

/* drawing → key */
.sys:has(.z1:hover) .k1, .sys:has(.z2:hover) .k2, .sys:has(.z3:hover) .k3,
.sys:has(.z4:hover) .k4, .sys:has(.z5:hover) .k5, .sys:has(.z6:hover) .k6,
.sys:has(.z7:hover) .k7 { border-top-color: var(--ink); color: var(--ink); }

.sys:has(.z1:hover) .k1 .key-n, .sys:has(.z2:hover) .k2 .key-n,
.sys:has(.z3:hover) .k3 .key-n, .sys:has(.z4:hover) .k4 .key-n,
.sys:has(.z5:hover) .k5 .key-n, .sys:has(.z6:hover) .k6 .key-n,
.sys:has(.z7:hover) .k7 .key-n { background: var(--accent); border-color: var(--accent); color: var(--bg); }

/* --------------------------------------------------------------------------
   5. Key
   -------------------------------------------------------------------------- */

.keys {
  grid-column: 1 / -1;
  grid-row: 4;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--gap);
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}

.keys li { display: flex; min-width: 0; }

.key {
  display: grid;
  flex: 1;
  grid-template-columns: 22px minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  column-gap: 12px;
  padding: 14px 0 28px;
  border-top: 1px solid var(--line);
  color: var(--ink-2);
  transition: border-color .4s var(--ease), color .3s var(--ease);
}

.key-n {
  grid-row: 1 / span 3;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
  transition: background-color .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease);
}

.key-name { color: var(--ink); font-size: 15px; font-weight: 500; letter-spacing: -.01em; line-height: 22px; }
.key-text { margin: 4px 0 0; font-size: 14px; line-height: 1.5; text-wrap: pretty; }

.key-go {
  margin-top: 12px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 11px;
  transition: color .3s var(--ease);
}

.key:is(:hover, :focus-visible) { border-top-color: var(--ink); }
.key:is(:hover, :focus-visible) .key-n { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.key:is(:hover, :focus-visible) .key-go { color: var(--ink-2); }
.key:is(:hover, :focus-visible) .key-go .arr { transform: translateY(2px); }
.key:focus-visible { outline-offset: 6px; }

/* the eighth cell: what isn't built yet */
.key--note { border-top-style: dashed; }
.key--note .key-n { border-style: dashed; }
.key--note:hover { border-top-color: var(--line); }

/* --------------------------------------------------------------------------
   6. Loop
   One room, start to seal, in sixteen seconds: an agent from each instance
   takes its seat; seat a writes to the context (rules, assessment, allow) and
   the index mirrors it; seat b calls a connector (rules only); a message from
   seat b is assessed and stopped; time runs out, the room seals and its
   receipt goes to the control plane. The base styles are the finished frame,
   which is what reduced motion shows. project.js pauses the loop while the
   map is off screen.
   -------------------------------------------------------------------------- */

.sys { --t: 16s; }

.tr {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  stroke-linejoin: round;
}

.sys .s-seat { fill: var(--accent); stroke: var(--accent); }
.sys .s-ext  { stroke: var(--accent); }
.s-ttl { fill: var(--dia-soft); transform-box: fill-box; transform-origin: 0 50%; transform: scaleX(.4); }
.s-x   { fill: none; stroke: var(--accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.s-cw  { fill: none; stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.s-ix  { fill: var(--accent); }

.s-ta1, .s-tb1, .s-ta2, .s-mir, .s-tb2, .s-td, .s-seal, .s-store,
.s-sa, .s-sb, .s-cw, .s-ix, .s-ext, .s-x, .s-ttl, .s-rcpt {
  animation: var(--t) linear infinite both;
}
.s-ta1   { animation-name: s-ta1; }
.s-tb1   { animation-name: s-tb1; }
.s-sa    { animation-name: s-sa; }
.s-sb    { animation-name: s-sb; }
.s-ta2   { animation-name: s-ta2; }
.s-cw    { animation-name: s-cw; }
.s-mir   { animation-name: s-mir; }
.s-ix    { animation-name: s-ix; }
.s-tb2   { animation-name: s-tb2; }
.s-ext   { animation-name: s-ext; }
.s-td    { animation-name: s-td; }
.s-x     { animation-name: s-x; }
.s-ttl   { animation-name: s-ttl; }
.s-seal  { animation-name: s-seal; }
.s-rcpt  { animation-name: s-rcpt; }
.s-store { animation-name: s-store; }

.sys .d-flow { animation: d-beat 1.4s linear infinite; }
.sys.is-off .sys-fig * { animation-play-state: paused; }

/* each agent takes its seat; both leave when the room seals */
@keyframes s-ta1 {
  0%, 2%    { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  8%, 84%   { stroke-dashoffset: 0; opacity: 1; }
  88%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-tb1 {
  0%, 9%    { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  15%, 84%  { stroke-dashoffset: 0; opacity: 1; }
  88%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-sa {
  0%, 8%    { fill: var(--plate); stroke: var(--dia); }
  10%, 84%  { fill: var(--accent); stroke: var(--accent); }
  88%, 100% { fill: var(--plate); stroke: var(--dia); }
}
@keyframes s-sb {
  0%, 15%   { fill: var(--plate); stroke: var(--dia); }
  17%, 84%  { fill: var(--accent); stroke: var(--accent); }
  88%, 100% { fill: var(--plate); stroke: var(--dia); }
}

/* seat a writes: rules, assessment, allow, and the index mirrors the write */
@keyframes s-ta2 {
  0%, 20%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  30%, 36%  { stroke-dashoffset: 0; opacity: 1; }
  40%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-cw {
  0%, 29%   { opacity: 0; }
  31%, 84%  { opacity: 1; }
  88%, 100% { opacity: 0; }
}
@keyframes s-mir {
  0%, 29%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  33%, 36%  { stroke-dashoffset: 0; opacity: 1; }
  40%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-ix {
  0%, 32%   { opacity: 0; }
  34%, 84%  { opacity: 1; }
  88%, 100% { opacity: 0; }
}

/* seat b calls a connector: seat rules only, then out through the mesh */
@keyframes s-tb2 {
  0%, 42%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  50%, 55%  { stroke-dashoffset: 0; opacity: 1; }
  59%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-ext {
  0%, 49%   { stroke: var(--dia); }
  50%, 55%  { stroke: var(--accent); }
  59%, 100% { stroke: var(--dia); }
}

/* a message from seat b passes the rules and is stopped by the assessment */
@keyframes s-td {
  0%, 60%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  68%, 74%  { stroke-dashoffset: 0; opacity: 1; }
  78%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-x {
  0%, 67%   { stroke: var(--dia); }
  68%, 76%  { stroke: var(--accent); }
  80%, 100% { stroke: var(--dia); }
}

/* time runs out across the whole loop; the room seals; the receipt goes home */
@keyframes s-ttl {
  0%        { transform: none; }
  80%, 97%  { transform: scaleX(0); }
  100%      { transform: none; }
}
@keyframes s-seal {
  0%, 80%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  83%, 95%  { stroke-dashoffset: 0; opacity: 1; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes s-rcpt {
  0%, 82%   { opacity: 0; transform: translateX(-6px); animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  86%, 95%  { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: none; }
}
@keyframes s-store {
  0%, 86%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
  92%, 95%  { stroke-dashoffset: 0; opacity: 1; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

/* --------------------------------------------------------------------------
   7. Pager
   -------------------------------------------------------------------------- */

.pager {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  margin-top: clamp(112px, 12vw, 176px);
}

.pager a {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  transition: border-color .4s var(--ease);
}

.pg-prev { grid-column: 1 / span 6; }
.pg-next { grid-column: 7 / -1; align-items: flex-end; text-align: right; }

.pg-dir { color: var(--ink-3); font-family: var(--mono); font-size: 12px; }

.pg-name {
  color: var(--ink-2);
  font-size: clamp(1.25rem, 1rem + .9vw, 1.75rem);
  font-weight: 500;
  letter-spacing: -.025em;
  transition: color .3s var(--ease);
}

.pager a:hover { border-top-color: var(--ink); }
.pager a:hover .pg-name { color: var(--ink); }
.pg-prev:hover .arr { transform: translateX(-3px); }
.pg-next:hover .arr { transform: translateX(3px); }

.proj .colophon { margin-top: 64px; }
.colophon .top { grid-column: 6 / span 5; }
.colophon .top:hover .arr { transform: translateY(-2px); }

/* --------------------------------------------------------------------------
   8. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1279px) {
  .sys .d-lbl { font-size: 11.5px; }
}

@media (max-width: 1099px) {
  .sys .d-lbl { font-size: 12.5px; }
  .proj .plate .d-lbl { font-size: 10.5px; }
  .p-index, .sys-spec { grid-column: 8 / -1; }
  .p-deck, .p-note { grid-column: 1 / span 6; }
  .keys { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .colophon .top { grid-column: 7 / span 4; }
}

/* Tablets and phones: one column. The map keeps its drawing and numbers;
   the key carries the words. */
@media (max-width: 899px) {
  .p-head h1, .p-head .line { grid-column: 1 / -1; }
  .p-deck, .p-note { grid-column: 1 / span 9; }
  .p-index { grid-column: 1 / span 9; grid-row: 6; align-self: start; margin-top: 48px; }

  .sys-lead { grid-column: 1 / span 9; padding-top: 28px; }
  .sys-spec { grid-column: 1 / span 9; grid-row: 3; align-self: start; margin-top: 28px; }
  .sys-fig { grid-row: 4; margin-top: 40px; }
  .keys { grid-row: 5; }
  .sys .d-lbl { display: none; }
  .co { transform: scale(1.8); }
  .tr { stroke-width: 3; }

  .proj .plate { max-width: 600px; }

  .pager { display: flex; justify-content: space-between; gap: 24px; }
  .pager a { flex: 1; }
}

@media (max-width: 599px) {
  .crumbs .count { display: none; }
  .p-deck, .p-note, .p-index, .sys-lead, .sys-spec { grid-column: 1 / -1; }
  .keys { grid-template-columns: minmax(0, 1fr); }
  .key { padding-bottom: 20px; }
  .co { transform: scale(2.8); }
  .tr { stroke-width: 4.5; }

  .proj .plate .d-lbl { display: inline; font-size: 11px; }
}

@media (max-width: 479px) {
  .proj .plate .d-lbl { font-size: 13px; }
}
