/* ==========================================================================
   Zion Rubin — the Zion OS page
   Loaded after home.css and project.css. The page keeps the project template
   and wears Zion OS's own design language (DESIGN.md in the OS repo): warm
   paper and ink, square windows with pinstriped title bars and hard offset
   drops, mono for labels, a serif for reading, inversion on hover, and
   stepped motion. Nothing here eases.
   Sections: tokens · type · head · sheets · windows · system map · key ·
             loop · pager · responsive
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   The OS palette under the site's token names, plus the window chrome. The
   same three blocks as home.css: light, dark by system, dark by choice.
   Reading text is set in the serif, so --sans (home.css's body face) points
   at Fraunces.
   -------------------------------------------------------------------------- */

.os {
  --bg: #f2efe7;
  --plate: #fdfbf6;
  --ink: #171613;
  --ink-2: #55524a;
  --ink-3: #6d695e;
  --line: #d3ccbb;
  --line-strong: #8b877c;
  --grid: rgba(23, 22, 19, .05);
  --dia: rgba(23, 22, 19, .6);
  --dia-soft: rgba(23, 22, 19, .22);
  --fill: rgba(23, 22, 19, .07);
  --accent: #b23a20;

  --win: #171613;
  --ctl: #171613;
  --grip: #b6ae99;
  --stripe: rgba(23, 22, 19, .16);
  --stripe-idle: rgba(23, 22, 19, .06);
  --drop: 2px 2px 0 0 rgba(23, 22, 19, .14);
  --drop-up: 4px 4px 0 0 rgba(23, 22, 19, .22);

  --sans: "Fraunces", ui-serif, Georgia, serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --pixel: "Silkscreen", "JetBrains Mono", ui-monospace, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .os {
    --bg: #12120f;
    --plate: #171713;
    --ink: #ece7d9;
    --ink-2: #a49e8d;
    --ink-3: #888273;
    --line: #33322b;
    --line-strong: #6e695d;
    --grid: rgba(236, 231, 217, .05);
    --dia: rgba(236, 231, 217, .56);
    --dia-soft: rgba(236, 231, 217, .2);
    --fill: rgba(236, 231, 217, .07);
    --accent: #e07a4f;

    --win: #5d5849;
    --ctl: #857f70;
    --grip: #4a483f;
    --stripe: rgba(236, 231, 217, .16);
    --stripe-idle: rgba(236, 231, 217, .06);
    --drop: 2px 2px 0 0 rgba(0, 0, 0, .5);
    --drop-up: 4px 4px 0 0 rgba(0, 0, 0, .65);
  }
}

:root[data-theme="dark"] .os {
  --bg: #12120f;
  --plate: #171713;
  --ink: #ece7d9;
  --ink-2: #a49e8d;
  --ink-3: #888273;
  --line: #33322b;
  --line-strong: #6e695d;
  --grid: rgba(236, 231, 217, .05);
  --dia: rgba(236, 231, 217, .56);
  --dia-soft: rgba(236, 231, 217, .2);
  --fill: rgba(236, 231, 217, .07);
  --accent: #e07a4f;

  --win: #5d5849;
  --ctl: #857f70;
  --grip: #4a483f;
  --stripe: rgba(236, 231, 217, .16);
  --stripe-idle: rgba(236, 231, 217, .06);
  --drop: 2px 2px 0 0 rgba(0, 0, 0, .5);
  --drop-up: 4px 4px 0 0 rgba(0, 0, 0, .65);
}

/* --------------------------------------------------------------------------
   2. Type
   Mono speaks (labels, states, metadata), the serif announces and carries
   the reading, Silkscreen stamps the numbers.
   -------------------------------------------------------------------------- */

.os :focus-visible { outline: 1px solid var(--ink); outline-offset: 1px; }
.os .arr { transition: none; }

/* micro-labels: 10px capitals, wide tracking */
.os .obj-meta, .os .obj-tags, .os .p-k, .os .key-go, .os .pg-dir,
.os figcaption span:first-child, .os .obj-spec dt {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
}

/* controls: 11px capitals */
.os .crumbs, .os .colophon, .os .key-name {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.os .obj-tags { gap: 4px 16px; }

.os .obj-n {
  font-family: var(--pixel);
  font-size: 16px;
  letter-spacing: 0;
  line-height: 1;
  transition: none;
}

/* --------------------------------------------------------------------------
   3. Head
   The contents sit in a small window, like the OS launcher.
   -------------------------------------------------------------------------- */

.os .crumbs a,
.os .colophon a {
  margin: -3px -6px;
  padding: 3px 6px;
  transition: none;
}
.os .crumbs a:is(:hover, :focus-visible),
.os .colophon a:is(:hover, :focus-visible) { background: var(--ink); color: var(--bg); }

.os .p-head h1 {
  font-size: clamp(2.75rem, 1.9rem + 3.6vw, 4.75rem);
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: .95;
}

/* a cursor after the name */
.os .p-head h1::after {
  content: "";
  display: inline-block;
  width: .42em;
  height: .09em;
  margin-left: .1em;
  background: var(--accent);
  animation: os-blink 1.1s step-end infinite;
}

@keyframes os-blink { 50% { opacity: 0; } }

.os .p-head .line {
  max-width: 30ch;
  font-size: clamp(1.25rem, 1.05rem + .8vw, 1.75rem);
  line-height: 1.3;
  letter-spacing: -.01em;
}

.os .p-deck, .os .p-note { font-size: 1.0625rem; line-height: 1.6; }
.os .p-k { margin-bottom: 8px; }

.os .p-note a { transition: none; }
.os .p-note a:is(:hover, :focus-visible) {
  background: var(--ink);
  color: var(--bg);
  text-decoration-color: var(--ink);
}

.os .p-index {
  position: relative;
  padding-top: 28px;
  border: 1px solid var(--win);
  background:
    linear-gradient(var(--win), var(--win)) 0 27px / 100% 1px no-repeat,
    repeating-linear-gradient(to bottom, var(--stripe-idle) 0, var(--stripe-idle) 1px, transparent 1px, transparent 3px) 0 0 / 100% 27px no-repeat,
    var(--plate);
  box-shadow: var(--drop);
}

.os .p-index::before {
  content: "Contents";
  content: "Contents" / "";
  position: absolute;
  top: 7px;
  left: 8px;
  padding: 0 6px;
  background: var(--plate);
  color: var(--ink);
  font: 500 11px/14px var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
}

.os .p-index ol { border-top: 0; }
.os .p-index li:last-child a { border-bottom: 0; }

.os .p-index a {
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  transition: none;
}

.os .ix-n, .os .p-index .arr { font-size: 11px; transition: none; }
.os .p-index a:is(:hover, :focus-visible) { background: var(--ink); color: var(--bg); }
.os .p-index a:is(:hover, :focus-visible) .arr { color: var(--bg); }

/* --------------------------------------------------------------------------
   4. Sheets
   -------------------------------------------------------------------------- */

.os .obj, .os .obj-spec dd { transition: none; }

.os .obj-name { font-weight: 500; letter-spacing: -.02em; }
.os .obj-line { font-size: 1.125rem; line-height: 1.45; }

.os .p-text { max-width: 48ch; font-size: 1rem; line-height: 1.65; }
.os .p-text code { font-size: .8125em; }
.os .p-aside { font-size: 11px; }

.os .obj-spec div { grid-template-columns: 96px minmax(0, 1fr); }
.os .obj-spec dt { line-height: 18px; }

/* --------------------------------------------------------------------------
   5. Windows
   Every figure is an OS window: a 1px frame, a pinstriped title bar with a
   knocked-out title and square controls, a corner grip, and a hard drop
   that grows when its sheet is in front.
   -------------------------------------------------------------------------- */

.os .plate-art {
  position: relative;
  border: 1px solid var(--win);
  box-shadow: var(--drop);
  transition: none;
}

.os .obj:is(:hover, :focus-within, .is-active) .plate-art,
.os .sys-fig .plate-art { border-color: var(--win); box-shadow: var(--drop-up); }

/* three stepped pixel rules in the corner */
.os .plate-art::after {
  content: "";
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 9px;
  height: 9px;
  background:
    linear-gradient(var(--grip), var(--grip)) 8px 0 / 1px 9px no-repeat,
    linear-gradient(var(--grip), var(--grip)) 5px 3px / 1px 6px no-repeat,
    linear-gradient(var(--grip), var(--grip)) 2px 6px / 1px 3px no-repeat;
  pointer-events: none;
}

.win-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 28px;
  padding: 0 7px 0 8px;
  border-bottom: 1px solid var(--win);
  background-image: repeating-linear-gradient(to bottom, var(--stripe-idle) 0, var(--stripe-idle) 1px, transparent 1px, transparent 3px);
}

.sys-fig .win-bar { height: 32px; }

.os .obj:is(:hover, :focus-within, .is-active) .win-bar,
.os .sys-fig .win-bar {
  background-image: repeating-linear-gradient(to bottom, var(--stripe) 0, var(--stripe) 1px, transparent 1px, transparent 3px);
}

.win-title {
  min-width: 0;
  padding: 0 6px;
  overflow: hidden;
  background: var(--plate);
  color: var(--ink-3);
  font: 500 11px/14px var(--mono);
  letter-spacing: .14em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.os .obj:is(:hover, :focus-within, .is-active) .win-title,
.os .sys-fig .win-title { color: var(--ink); }

.win-ctl {
  display: flex;
  flex: none;
  gap: 6px;
  padding-left: 6px;
  background: var(--plate);
}

.win-ctl i {
  position: relative;
  display: block;
  width: 13px;
  height: 13px;
  border: 1px solid var(--ctl);
  background: var(--plate);
  color: var(--ink);
}

/* 9×9 glyphs, drawn a pixel at a time */
.win-ctl i::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 2px;
  width: 1px;
  height: 1px;
  background: currentColor;
}

.win-ctl .g-min::before { top: 7px; width: 7px; }
.win-ctl .g-max::before { width: 7px; height: 7px; background: none; box-shadow: inset 0 0 0 1px currentColor; }
.win-ctl .g-x::before {
  box-shadow:
    1px 1px currentColor, 2px 2px currentColor, 3px 3px currentColor,
    4px 4px currentColor, 5px 5px currentColor, 6px 6px currentColor,
    6px 0 currentColor, 5px 1px currentColor, 4px 2px currentColor,
    2px 4px currentColor, 1px 5px currentColor, 0 6px currentColor;
}

/* --------------------------------------------------------------------------
   6. Drawings and the system map
   Square callouts, crisp rectangles, and the eighth kernel block wired in
   (project.css wires keys and zones one to seven).
   -------------------------------------------------------------------------- */

.os .dia rect, .os .d-grid { shape-rendering: crispEdges; }
.os .d-ko { fill: var(--plate); }

.os .zone { transition: none; }

.os .co rect {
  fill: var(--plate);
  stroke: var(--ctl);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.os .co text {
  fill: var(--ink);
  font-family: var(--pixel);
  font-size: 8px;
  font-weight: 400;
}

.sys:has(.k8:is(:hover, :focus-visible)) .zone:not(.z8) { opacity: .22; }

/* key → drawing: the callout turns to the accent */
.os .sys:has(.k1:is(:hover, :focus-visible)) .z1 .co rect,
.os .sys:has(.k2:is(:hover, :focus-visible)) .z2 .co rect,
.os .sys:has(.k3:is(:hover, :focus-visible)) .z3 .co rect,
.os .sys:has(.k4:is(:hover, :focus-visible)) .z4 .co rect,
.os .sys:has(.k5:is(:hover, :focus-visible)) .z5 .co rect,
.os .sys:has(.k6:is(:hover, :focus-visible)) .z6 .co rect,
.os .sys:has(.k7:is(:hover, :focus-visible)) .z7 .co rect,
.os .sys:has(.k8:is(:hover, :focus-visible)) .z8 .co rect,
.os .zone:not(.z0):hover .co rect { fill: var(--accent); stroke: var(--accent); }

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

/* --------------------------------------------------------------------------
   7. Key
   Hover, focus, or the matching part of the drawing inverts a key.
   -------------------------------------------------------------------------- */

.os .keys { margin-top: 48px; }

.os .key {
  padding: 12px 12px 24px;
  border-top-color: var(--line);
  transition: none;
}

.os .key-n {
  border-color: var(--ctl);
  border-radius: 0;
  background: var(--plate);
  color: var(--ink);
  font-family: var(--pixel);
  font-size: 8px;
  font-weight: 400;
  transition: none;
}

.os .key-name { font-weight: 500; line-height: 22px; }
.os .key-text { margin-top: 6px; font-size: 15px; }
.os .key-go { margin-top: 14px; transition: none; }

.os .key:is(:hover, :focus-visible),
.os .sys:has(.z1:hover) .k1, .os .sys:has(.z2:hover) .k2,
.os .sys:has(.z3:hover) .k3, .os .sys:has(.z4:hover) .k4,
.os .sys:has(.z5:hover) .k5, .os .sys:has(.z6:hover) .k6,
.os .sys:has(.z7:hover) .k7, .os .sys:has(.z8:hover) .k8 {
  background: var(--ink);
  border-top-color: var(--ink);
  color: var(--bg);
}

.os .key:is(:hover, :focus-visible) :is(.key-name, .key-go),
.os .sys:has(.z1:hover) .k1 :is(.key-name, .key-go), .os .sys:has(.z2:hover) .k2 :is(.key-name, .key-go),
.os .sys:has(.z3:hover) .k3 :is(.key-name, .key-go), .os .sys:has(.z4:hover) .k4 :is(.key-name, .key-go),
.os .sys:has(.z5:hover) .k5 :is(.key-name, .key-go), .os .sys:has(.z6:hover) .k6 :is(.key-name, .key-go),
.os .sys:has(.z7:hover) .k7 :is(.key-name, .key-go), .os .sys:has(.z8:hover) .k8 :is(.key-name, .key-go) { color: var(--bg); }

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

.os .key:focus-visible { outline-offset: 2px; }

/* --------------------------------------------------------------------------
   8. Loop
   One turn in sixteen seconds, in steps: the request comes down from chat,
   across the bus and through identity; the router picks apps; context is
   read from sessions and memory; the model calls a tool, which writes memory
   and emits a chart surface; the surface streams back over the bus to a
   window; after the reply, memory is extracted. Each phase leaves a span
   along the bottom. The base styles are the finished frame, which is what
   reduced motion shows, and project.js pauses the loop off screen.
   -------------------------------------------------------------------------- */

.os .tr { stroke-linejoin: miter; }
.os .sys .d-flow { animation-timing-function: steps(3, end); }

.o-in, .o-r1, .o-cx, .o-r2, .o-call, .o-wr, .o-ui, .o-out, .o-ex,
.o-row, .o-surf, .o-sp1, .o-sp2, .o-sp3, .o-sp4, .o-sp5, .o-sp6, .o-sp7 {
  animation: var(--t) step-end infinite both;
}

.o-in   { animation-name: o-in; }
.o-sp1  { animation-name: o-sp1; }
.o-sp2  { animation-name: o-sp2; }
.o-r1   { animation-name: o-r1; }
.o-cx   { animation-name: o-cx; }
.o-sp3  { animation-name: o-sp3; }
.o-r2   { animation-name: o-r2; }
.o-sp4  { animation-name: o-sp4; }
.o-call { animation-name: o-call; }
.o-row  { animation-name: o-row; }
.o-sp5  { animation-name: o-sp5; }
.o-wr   { animation-name: o-wr; }
.o-ui   { animation-name: o-ui; }
.o-out  { animation-name: o-out; }
.o-sp6  { animation-name: o-sp6; }
.o-surf { animation-name: o-surf; }
.o-sp7  { animation-name: o-sp7; }
.o-ex   { animation-name: o-ex; }

/* in: down from chat, across the bus, through identity to the router */
@keyframes o-in {
  0%, 2%    { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(8, end); }
  10%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-sp1 { 0% { opacity: 0; } 10% { opacity: 1; } 92%, 100% { opacity: 0; } }

/* routed, then context from sessions and memory */
@keyframes o-sp2 { 0% { opacity: 0; } 12% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-r1 {
  0%, 13%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(2, end); }
  15%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-cx {
  0%, 16%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(4, end); }
  20%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-sp3 { 0% { opacity: 0; } 20% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-r2 {
  0%, 22%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(2, end); }
  24%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

/* the model thinks, then calls a tool */
@keyframes o-sp4 { 0% { opacity: 0; } 26% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-call {
  0%, 30%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(3, end); }
  33%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-row { 0% { opacity: 0; } 33% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-sp5 { 0% { opacity: 0; } 34% { opacity: 1; } 92%, 100% { opacity: 0; } }

/* the tool writes memory and emits a surface */
@keyframes o-wr {
  0%, 37%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(3, end); }
  40%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-ui {
  0%, 43%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(3, end); }
  46%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

/* the surface streams back over the bus and opens on the desktop */
@keyframes o-out {
  0%, 48%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(10, end); }
  58%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes o-sp6  { 0% { opacity: 0; } 49% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-surf { 0% { opacity: 0; } 59% { opacity: 1; } 92%, 100% { opacity: 0; } }

/* after the reply: memory extraction */
@keyframes o-sp7 { 0% { opacity: 0; } 68% { opacity: 1; } 92%, 100% { opacity: 0; } }
@keyframes o-ex {
  0%, 70%   { stroke-dashoffset: 1; opacity: 1; animation-timing-function: steps(4, end); }
  74%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

/* --------------------------------------------------------------------------
   9. Pager and colophon
   -------------------------------------------------------------------------- */

.os .pager a {
  padding: 12px 12px 16px;
  border-top-color: var(--ink);
  transition: none;
}
.os .pager a:is(:hover, :focus-visible) { background: var(--ink); color: var(--bg); }
.os .pager a:is(:hover, :focus-visible) :is(.pg-dir, .pg-name) { color: var(--bg); }
.os .pg-name { letter-spacing: -.02em; transition: none; }

.os .colophon .mode {
  margin: -5px 0;
  padding: 4px 10px;
  border: 1px solid var(--ctl);
  background: var(--plate);
  letter-spacing: inherit;
  text-transform: uppercase;
  transition: none;
}
.os .colophon .mode:is(:hover, :focus-visible) { background: var(--ink); color: var(--bg); border-color: var(--ink); }

/* --------------------------------------------------------------------------
   10. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 899px) {
  .os .keys { margin-top: 40px; }
}

@media (max-width: 599px) {
  .os .key { padding: 12px 10px 20px; }
  .sys-fig .win-bar { height: 28px; }
}
