/* ============================================================================
   BRAIN DEMO — the interactive company-brain explorer.

   This is the centrepiece of the portfolio. It renders a normalised JSON
   description of a company brain as a browsable system: folder tree,
   constitution, rules, skills, agents, changelog, brand OS.

   Two things here exist in no brain DJ has shipped, and that is the point:
     1. A real collapsible folder tree. The earlier builds render theirs as a
        static ASCII block or a flat table.
     2. An ANNOTATION LAYER — margin notes explaining why each decision
        exists. Without it this is a file dump; with it, it is an argument.

   BRAND OS v3.0 "ATLAS". Four things in this sheet ran on tokens v3 deletes,
   and each one is rewritten rather than repointed, because in every case the
   colour was carrying meaning that v3 assigns somewhere else:

     --spark-ink   the eyebrow orange on light. Deleted with no replacement:
                   v3 has no text-legal orange at any size. Eyebrows and mono
                   labels on a light ground are Surface Steel, 7.44:1.
     --flag        the refusal red. Deleted: "there is no red in this palette."
                   A refusal is now carried by a 2px Midnight Green border and
                   the glyph — by weight, not by hue.
     --accent      the pale sea glass that spoke on dark. Deleted; on a
                   Midnight ground the voice is Paper White at 15.83:1, or
                   True North at 5.56:1 where it must stand apart.
     --data-1/2/3  the three-hue chart set. Deleted. v3 does data as "fills
                   only" in the signal pair, and the two charts here were
                   already single-measure, so each is now one flat fill —
                   which also retires the two gradients they were built on.
   ========================================================================= */

/* ---- SHELL --------------------------------------------------------------- */
.bd { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: clamp(24px, 4vw, 52px); align-items: start; }
@media (max-width: 1040px) { .bd { grid-template-columns: minmax(0, 1fr); } }

/* ---- TABS ---------------------------------------------------------------- */
.bd-tabs {
  display: flex; gap: 2px; flex-wrap: wrap; border-bottom: 1px solid var(--hairline);
  margin-bottom: 28px; position: sticky; top: var(--hd-h); z-index: 20;
  background: var(--grad-paper); background-attachment: fixed; padding-top: 4px;
}
.bd-tab {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600;
  letter-spacing: .04em; color: var(--faint); padding: 12px 15px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--t-hover) var(--ease), border-color var(--t-hover) var(--ease);
}
.bd-tab:hover { color: var(--ink); }
.bd-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--spark); }
.bd-panel { display: none; }
.bd-panel.on { display: block; animation: bdIn 260ms var(--ease); }
@keyframes bdIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ---- FOLDER TREE --------------------------------------------------------- */
.tree { font-family: var(--font-mono); font-size: var(--step--1); line-height: 1.75; overflow-x: auto; }
.tree ul { list-style: none; margin: 0; padding-left: 19px; border-left: 1px solid var(--hairline); }
.tree > ul { padding-left: 0; border-left: 0; }
.tree li { position: relative; }
.tree-row {
  display: flex; align-items: baseline; gap: 8px; padding: 3px 8px 3px 4px;
  border-radius: var(--r-sm); cursor: pointer; width: 100%; text-align: left;
  background: transparent; border: 0; font: inherit; color: var(--ink);
  transition: background var(--t-hover) var(--ease);
}
.tree-row:hover { background: var(--wash-primary); }
.tree-row.sel { background: var(--ink); color: var(--paper); }
.tree-row.sel .tree-meta { color: var(--dim-d); }
.tree-tw {
  flex: 0 0 12px; color: var(--faint); font-size: 10px; line-height: 1.9;
  transition: transform 180ms var(--ease);
}
.tree-row[aria-expanded="true"] .tree-tw { transform: rotate(90deg); }
.tree-row.leaf .tree-tw { visibility: hidden; }
.tree-nm { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.tree-row.dir .tree-nm { color: var(--primary); font-weight: 600; }
/* One row is selected at a time, so the directory name inside it is the one
   place on this panel True North appears — 5.56:1 on the Midnight fill, which
   is the only ground in the system where it is legal as type. */
.tree-row.sel.dir .tree-nm { color: var(--spark); }
.tree-meta { margin-left: auto; color: var(--faint); font-size: 10.5px; white-space: nowrap; }
.tree li[data-open="false"] > ul { display: none; }

/* ---- NODE DETAIL --------------------------------------------------------- */
.bd-detail {
  border: 1px solid var(--hairline); border-radius: var(--r); background: var(--card);
  padding: 20px 22px; margin-top: 18px; min-height: 150px;
}
.bd-detail-path {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .04em;
  color: var(--faint); margin-bottom: 10px; word-break: break-all;
}
.bd-detail h4 { font-size: var(--step-1); margin-bottom: .4em; }
.bd-detail .excerpt {
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7;
  background: var(--band); border-radius: var(--r-sm); padding: 14px 16px;
  margin-top: 14px; white-space: pre-wrap; overflow-x: auto; color: var(--muted);
}
.bd-empty { color: var(--faint); font-size: var(--step--1); font-style: italic; }

/* ---- ANNOTATION RAIL — the thing no brain of his has ------------------- */
.bd-rail { position: sticky; top: calc(var(--hd-h) + 50px); }
@media (max-width: 1040px) { .bd-rail { position: static; margin-top: 32px; } }
.anno {
  border-left: 2px solid var(--spark); padding: 2px 0 2px 16px; margin-bottom: 22px;
}
.anno-l {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--primary); display: block; margin-bottom: 5px;
}
.anno p { font-size: var(--step--1); line-height: 1.55; color: var(--muted); margin: 0; max-width: none; }
.anno q { font-style: italic; }

/* ---- CONSTITUTION -------------------------------------------------------- */
.const-sec { border-top: 1px solid var(--hairline); padding: 22px 0; }
.const-sec:first-child { border-top: 0; padding-top: 0; }
.const-n {
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600;
  color: var(--primary); margin-right: 10px;
}
.const-sec h3 { display: inline; font-size: var(--step-1); }
.const-body { margin-top: 14px; }
.const-body p { font-size: var(--step--1); }
.const-body ul { font-size: var(--step--1); color: var(--muted); padding-left: 20px; }
.const-body li { margin-bottom: 7px; }
.const-body li strong { color: var(--ink); }

/* ---- RULES / SKILLS / AGENTS -------------------------------------------- */
.rule {
  border: 1px solid var(--hairline); border-radius: var(--r); padding: 16px 18px;
  background: var(--card); display: flex; gap: 14px; align-items: flex-start;
}
/* The NEVER marker on a rule. Red is not available and no other hue may stand
   in for it, so it takes the shape v3 gives every failure state: a 2px
   Midnight Green border, the glyph, no fill. Midnight on the card is 15.83:1
   and the doubled border makes it the heaviest object in the row, which is
   what the red was doing before it was a colour. */
.rule-x {
  flex: 0 0 auto; font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  color: var(--ink); border: 2px solid var(--ink);
  background: transparent; border-radius: var(--r-sm); padding: 2px 7px; line-height: 1.4;
}
.rule p { margin: 0; font-size: var(--step--1); }
.rule b { display: block; margin-bottom: 3px; }

.skill { border: 1px solid var(--hairline); border-radius: var(--r); padding: 16px 18px; background: var(--card); }
.skill h4 { font-family: var(--font-mono); font-size: var(--step--1); color: var(--primary); margin-bottom: .45em; letter-spacing: .02em; }
.skill p { font-size: var(--step--1); color: var(--muted); margin: 0; }

/* ---- CHANGELOG ----------------------------------------------------------- */
.cl { border: 1px solid var(--hairline); border-radius: var(--r); overflow: hidden; background: var(--card); }
.cl details { border-bottom: 1px solid var(--hairline-soft); }
.cl details:last-child { border-bottom: 0; }
.cl summary {
  cursor: pointer; padding: 13px 18px; display: flex; gap: 14px; align-items: baseline;
  font-size: var(--step--1); list-style: none;
}
.cl summary::-webkit-details-marker { display: none; }
.cl summary:hover { background: var(--wash-primary); }
.cl summary::after { content: "+"; margin-left: auto; color: var(--faint); font-family: var(--font-mono); }
.cl details[open] summary::after { content: "\2013"; }
.cl-date { font-family: var(--font-mono); font-size: 11.5px; color: var(--faint); flex: 0 0 88px; }
.cl-body { padding: 0 18px 16px 120px; font-size: var(--step--1); color: var(--muted); }
@media (max-width: 620px) { .cl-body { padding-left: 18px; } }

/* ---- BRAND OS SWATCHES --------------------------------------------------- */
.sw { border: 1px solid var(--hairline); border-radius: var(--r); overflow: hidden; background: var(--card); }
.sw-chip { height: 76px; }
.sw-meta { padding: 11px 14px; }
.sw-nm { font-size: var(--step--1); font-weight: 600; }
.sw-hex { font-family: var(--font-mono); font-size: 11px; color: var(--faint); text-transform: uppercase; }
.sw-rule { font-size: 11.5px; color: var(--muted); margin-top: 6px; line-height: 1.45; }

/* ---- FILE INDEX SEARCH --------------------------------------------------- */
.bd-toolbar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.bd-search {
  flex: 1 1 240px; font-family: var(--font-body); font-size: var(--step--1);
  padding: 11px 15px; border: 1px solid var(--hairline); border-radius: var(--r);
  background: var(--card); color: var(--ink); min-height: 44px;
}
.bd-count { font-family: var(--font-mono); font-size: 11.5px; color: var(--faint); }

/* ---- SCRUB BANNER — visible on every confidential demo ------------------ */
.scrub {
  border: 1px solid color-mix(in srgb, var(--spark) 40%, transparent);
  background: var(--wash-spark); border-radius: var(--r);
  padding: 16px 20px; margin-bottom: 30px; font-size: var(--step--1);
}
/* The border and the wash are True North as a rule and a fill, which is legal
   on a light ground. The label is not: it is Midnight Green at 14.55:1 over the
   8% orange wash. Same banner, one law obeyed. */
.scrub b { display: block; font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink); margin-bottom: 6px; }
.scrub p { margin: 0; max-width: 78ch; }

/* ---- EVOLUTION CHART ----------------------------------------------------- */
/* ONE MEASURE, ONE HUE, ONE FLAT FILL. The bars were a two-stop gradient
   between --data-2 and --data-1; v3 allows exactly one gradient in the whole
   system and it is not this one. The fill is Meridian, which is what the
   signal pair is actually for — "data visualisation: fills only. Bars, nodes,
   tree branches, stat tiles. Never the axis, never the label."

   The labels flip to Midnight Green as a direct consequence. Paper White on
   Meridian is 3.01:1 and fails; Midnight Green on Meridian is 5.26:1 and
   passes at every size, which is the same measurement read the other way.

   The 11px key line carried opacity .86, which dropped it to 4.24:1 and under
   AA. The opacity is removed rather than nudged; the two lines already
   separate on size and weight. */
.evo { display: grid; gap: 3px; grid-template-columns: repeat(4, 1fr); align-items: end; height: 190px; margin: 30px 0 10px; }
.evo-bar { background: var(--beacon); border-radius: var(--r-sm) var(--r-sm) 0 0; position: relative; display: flex; flex-direction: column; justify-content: flex-end; padding: 10px; }
.evo-bar .v { font-family: var(--font-mono); font-size: var(--step-1); font-weight: 600; color: var(--ground); line-height: 1; }
.evo-bar .k { font-size: 11px; color: var(--ground); margin-top: 5px; }
.evo-x div { font-family: var(--font-mono); font-size: 11px; color: var(--dim-d); padding: 10px 0 0; border-top: 1px solid var(--hairline-d); max-width: 70ch; line-height: 1.5; }

/* ---- MOBILE --------------------------------------------------------------
   At 375px the seven tabs wrapped to three rows of sticky chrome, which with
   the header consumed a third of the viewport before any content. One
   scrollable row instead. */
@media (max-width: 700px) {
  .bd-tabs {
    flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x proximity;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .bd-tabs::-webkit-scrollbar { display: none; }
  .bd-tab { flex: 0 0 auto; scroll-snap-align: start; }
  .tree-meta { display: none; }          /* line counts are decoration; the width is not */
  .evo { grid-template-columns: 1fr; height: auto; gap: 8px; }
  .evo-bar { height: auto !important; min-height: 58px; flex-direction: row; align-items: baseline; gap: 12px; }
}

/* ---- PRESS FEEDBACK ------------------------------------------------------
   Every interactive surface in the brain demo previously responded only on
   click. Nothing acknowledged the press itself, which is the one thing that
   makes a control feel connected to the finger rather than to a callback.

   The asymmetry is deliberate and is what the two existing timing tokens were
   written for: --t-press (90ms) going in, --t-release (200ms) coming back.
   Fast to acknowledge, unhurried to let go. Reversing those two values makes
   the same interface feel broken, which is a good way to prove the point.

   No transform on the tree rows. They sit inside a scrollable monospace grid
   where a 1px nudge would fight the alignment that makes a tree readable.
   Colour carries the press instead.
   ------------------------------------------------------------------------ */
.bd-tab, .tree-row { transition-duration: var(--t-release); }
.bd-tab:active, .tree-row:active { transition-duration: var(--t-press); }

.bd-tab:active { color: var(--ink); background: var(--wash-primary); }
.tree-row:active { background: color-mix(in srgb, var(--primary) 16%, var(--card)); }
.tree-row.sel:active { background: color-mix(in srgb, var(--ink) 88%, var(--paper)); }

.cl summary, .cl details > summary { cursor: pointer; }
.cl summary:active { background: var(--wash-primary); transition-duration: var(--t-press); }

/* Coarse pointers get a real target without changing the density a file tree
   depends on. A 30px row is fine under a mouse and a coin toss under a thumb. */
@media (pointer: coarse) {
  .tree-row { padding-top: 7px; padding-bottom: 7px; }
  .bd-tab { padding-top: 15px; padding-bottom: 15px; }
}

/* ---- HORIZONTAL BAR CHART ------------------------------------------------
   Companion to .evo, for a measure whose values span two orders of magnitude
   (0, 3, 76, 5). Vertical bars at that spread cannot hold their own labels, so
   the labels move outside the marks: name left, bar centre, value right.
   Single measure, one hue, direct labels. The palette validator failed the
   three --data tokens as a CATEGORICAL set, which is fine, because nothing
   here is categorical: every chart on this site is one measure in one hue.

   v3 settled that argument by deleting the three tokens outright. The hue is
   Meridian, the fill is flat, and because the value sits OUTSIDE the bar on
   the dark ground rather than on the fill, it keeps Paper White at 15.83:1. */
.hbar { display: grid; gap: 10px; margin: 30px 0 10px; }
.hbar-row { display: grid; grid-template-columns: 110px 1fr 44px; gap: 12px; align-items: center; }
.hbar-k { font-size: 11px; color: var(--dim-d); text-align: right; }
.hbar-track { height: 14px; border-radius: 3px; background: color-mix(in srgb, var(--paper) 7%, transparent); position: relative; }
.hbar-fill { position: absolute; inset: 0 auto 0 0; border-radius: 3px; background: var(--beacon); min-width: 2px; }
.hbar-fill.zero { background: transparent; border-left: 2px solid var(--dim-d); border-radius: 0; min-width: 0; }
.hbar-v { font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600; color: var(--paper); }
@media (max-width: 700px) { .hbar-row { grid-template-columns: 84px 1fr 40px; } }

/* ---- CHANGELOG OPEN ------------------------------------------------------
   details/summary snapped open with no bridge. The reveal now announces
   itself: content fades and settles in 200ms. State indication, occasional
   frequency, inside the 260ms budget. The global reduced-motion rule in
   tokens.css removes it entirely rather than slowing it. */
.cl details[open] .cl-body { animation: clOpen 200ms var(--ease); }
@keyframes clOpen { from { opacity: 0; transform: translateY(-4px); } }
