/* Home, replacement world: a dense low-prose index on living black.
   Everything is a row. Type stays small. The living field is bound to the
   opening panel, not to the page. */

* { box-sizing: border-box; }
html { overflow-x: clip; scroll-behavior: smooth; }
body {
  margin: 0;
  overflow-x: clip;
  background: var(--void);
  color: var(--paper);
  font: 400 15px/1.55 Archivo, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.col { width: var(--col); margin-inline: auto; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }


/* ---- chrome --------------------------------------------------------- */
/* lifted over the hero so the full-bleed panel starts at the very top of the
   page instead of sitting under a strip of dead ground */
body { position: relative; }
.chrome {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 30;
  display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 0;
}
.chrome-mark { display: inline-flex; align-items: center; min-height: 44px; }
.chrome-mark svg { width: 18px; height: 18px; }
.chrome-nav { display: flex; align-items: center; gap: 2px; margin-right: -10px; }
.chrome-nav a {
  min-height: 44px; display: inline-flex; align-items: center; padding: 0 10px;
  color: var(--gray); text-decoration: none;
  font: 400 13px/1 Archivo, sans-serif;
  transition: color .2s var(--ease);
}
.chrome-nav a:hover { color: var(--paper); }

/* ---- opening -------------------------------------------------------- */
/* The living field is a property of this panel, not a page background. The
   panel is full-bleed so the field has room to be seen, which is the point:
   it is the signature of this world and the previous version scrimmed it into
   invisibility. */
.opening {
  position: relative; isolation: isolate;
  min-height: clamp(430px, 66vh, 660px);
  display: flex; align-items: flex-end;
  padding: clamp(48px, 8vw, 104px) 0 clamp(66px, 8.5vw, 116px);
  margin-bottom: clamp(8px, 2vw, 26px);
  background: #000;   /* jet: the field is the only thing that lifts off it */
  border-bottom: 1px solid var(--line);
}
.atmos { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; display: block; }
/* the scrim only has to protect the copy column, so it releases early and
   leaves the right half of the panel to the field */
.opening::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(96deg, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, .66) 30%, rgba(0, 0, 0, .16) 58%, rgba(0, 0, 0, 0) 82%),
    linear-gradient(180deg, rgba(0, 0, 0, .7) 0%, rgba(0, 0, 0, 0) 26%, rgba(0, 0, 0, 0) 74%, rgba(0, 0, 0, .8) 100%);
}
.opening-body { position: relative; }
.name {
  margin: 0 0 clamp(20px, 2.6vw, 34px);
  font: 400 clamp(46px, 8.4vw, 96px)/0.86 "Bodoni Moda", Didot, Georgia, serif;
  letter-spacing: -.026em;
}
/* the surname drops and indents, so the name reads as a mark rather than a line
   of text, and the indent sets the left edge the statement hangs from */
.name span { display: block; padding-left: .5em; }
/* The name sits on the field rather than beside it, so it carries a shadow of
   its own ground. This is what lets the scrim release early enough for the
   interference to read behind the letterforms. */
.name, .opening h1 { text-shadow: 0 2px 20px rgba(0, 0, 0, .85); }
.opening h1 {
  margin: 0; max-width: 34ch;
  font: 400 clamp(17px, 1.75vw, 21px)/1.55 Archivo, sans-serif; letter-spacing: -.005em;
}
.opening h1 em { font-style: normal; color: var(--signal); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: clamp(24px, 3vw, 36px); margin-left: -2px; }
.actions a {
  min-height: 44px; display: inline-flex; align-items: center; padding: 0 12px;
  color: var(--gray); text-decoration: none; font: 400 13px/1 Archivo, sans-serif;
  transition: color .2s var(--ease);
}
.actions a:hover { color: var(--paper); }

/* ---- bands ---------------------------------------------------------- */
/* more air above a heading than below it, and enough room between bands that
   the three lists read as separate bodies of work rather than one long table */
.band { padding-top: clamp(56px, 7.5vw, 96px); }
.rule { display: flex; align-items: center; gap: 16px; padding-bottom: 6px; }
.rule h2 { margin: 0; color: var(--paper); font: 500 11px/1 "JetBrains Mono", monospace; letter-spacing: .16em; text-transform: uppercase; }
.rule::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.rule-link { order: 3; min-height: 44px; display: inline-flex; align-items: center; gap: 7px; padding-left: 10px; color: var(--dim); text-decoration: none; font: 400 11px/1 "JetBrains Mono", monospace; letter-spacing: .1em; text-transform: uppercase; transition: color .2s var(--ease); }
.rule-link span { color: var(--signal); }
.rule-link:hover { color: var(--paper); }
.band-note { margin: 14px 0 0; color: var(--dim); font-size: 13px; }

.rows { list-style: none; margin: 14px 0 0; padding: 0; }
.rows li + li { border-top: 1px solid var(--line); }
.row {
  display: grid; grid-template-columns: 44px minmax(0, 1fr) auto;
  align-items: center; gap: 18px;
  padding: 20px 12px; margin-inline: -12px;
  border-radius: 8px; color: inherit; text-decoration: none;
  transition: background .22s var(--ease);
}
.row:hover { background: rgba(244, 242, 239, .035); }
.rows--text .row { grid-template-columns: minmax(0, 1fr) auto; padding-top: 17px; padding-bottom: 17px; }
.tile { display: block; width: 44px; height: 44px; border-radius: 7px; overflow: hidden; background: #141317; border: 1px solid var(--line); }
.tile img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: left top; }
.tile--empty { background: repeating-linear-gradient(135deg, #141317 0 4px, #0F0E12 4px 8px); }

/* ---- built tiles ----------------------------------------------------
   A cropped screenshot at 44px is not a picture of anything; it is a smear
   that happens to be the right colour. So the tile carries the project's own
   logomark in white instead, on a ground where the colour exists only as
   grain and never as a fill.

   The grain is not a texture that resembles the hero. It is the hero: the
   same value-noise, fBm and ridge functions out of atmosphere.js, baked
   static and tinted per project by scripts/bake-tile-noise.mjs, run at a
   higher frequency so the filaments stay dense at 44px instead of arriving as
   two fat smears. Mean coverage lands near 8 percent, which is where the
   opening panel sits, so the tiles read as chips of the same field.

   Re-bake with `node scripts/bake-tile-noise.mjs` if a brand colour moves. */
.tile--mark { display: grid; place-items: center; background-color: var(--ink); }
/* Sized against the tile, not in pixels. `width: auto` reads the SVG's own
   intrinsic box (168x150 here, not the HTML width attribute), which filled the
   tile edge to edge; and a fixed px width would not follow the tile down to
   34px on mobile. The two marks carry different visual weight, so they are
   balanced by eye rather than set to one shared number: the triangle is open
   and needs the extra room, the leaf is solid and would shout at the same size. */
.tile--mark img {
  height: auto; object-fit: contain;
  transition: transform .3s var(--ease);
}
.tile--scalisage img { width: 55%; }
.tile--boc img { width: 50%; }
/* Drawn at device resolution, and deliberately NOT pixelated: the dots are
   round, and a pixelated hint is what turned every one of them into a hard
   square block. */
.tile-field {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.tile--mark { position: relative; }
.tile--mark img { position: relative; z-index: 1; }
/* the row already answers the pointer; the tile only leans in, so the mark
   lifts off its field without the row turning into two competing responses */
.row:hover .tile--mark { border-color: var(--line-hi); }
.row:hover .tile--mark img { transform: scale(1.08); }
@media (prefers-reduced-motion: reduce) {
  .tile--mark img, .row:hover .tile--mark img { transition: none; transform: none; }
}
.row-body { display: grid; gap: 5px; min-width: 0; }
.row-title { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font: 500 14.5px/1.35 Archivo, sans-serif; }
.rows--text .row-title { font-weight: 400; color: var(--paper); }
.row:hover .row-title { color: #FFFFFF; }
.row-note { color: var(--gray); font-size: 13px; line-height: 1.4; }
.row-meta { color: var(--dim); font: 400 11px/1 "JetBrains Mono", monospace; letter-spacing: .08em; white-space: nowrap; }
.badge {
  font: 400 9.5px/1 "JetBrains Mono", monospace; letter-spacing: .12em; text-transform: uppercase;
  color: var(--dim); border: 1px solid var(--line); border-radius: 4px; padding: 3px 6px; font-style: normal;
}
.badge.live { color: var(--signal); border-color: rgba(255, 74, 28, .3); }

/* ---- channel -------------------------------------------------------- */
.channel-form { display: grid; gap: 10px; margin-top: 20px; }
.field-pair { display: grid; gap: 8px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.channel-form input, .channel-form textarea {
  width: 100%; padding: 12px 13px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--ink); color: var(--paper);
  font: 400 14px/1.5 Archivo, sans-serif;
  transition: border-color .2s var(--ease);
}
.channel-form textarea { min-height: 92px; resize: vertical; }
.channel-form ::placeholder { color: var(--dim); }
.channel-form input:focus, .channel-form textarea:focus { outline: none; border-color: var(--line-hi); }
.channel-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-top: 2px; }
.channel-status { margin: 0; color: var(--dim); font-size: 12.5px; }
.channel-status[data-state="error"] { color: var(--signal); }

/* ---- footer --------------------------------------------------------- */
.foot { margin-top: clamp(64px, 8vw, 104px); border-top: 1px solid var(--line); }
.foot-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 20px; padding: 14px 0 18px; }
.foot-links { display: flex; flex-wrap: wrap; gap: 2px; margin-right: -10px; }
.foot-links a { min-height: 44px; display: inline-flex; align-items: center; padding: 0 10px; color: var(--gray); text-decoration: none; font: 400 12.5px/1 Archivo, sans-serif; transition: color .2s var(--ease); }
.foot-links a:hover { color: var(--paper); }
.foot-note { color: var(--dim); font: 400 11px/1 "JetBrains Mono", monospace; letter-spacing: .08em; }

/* The height is driven by the variable the script sets after it measures the
   type. The canvas is taken out of flow so its 300x150 intrinsic ratio cannot
   stretch the footer to 640px before that measurement happens. */
.wordmark { position: relative; display: block; line-height: 0; text-decoration: none; width: 100%; height: var(--wordmark-height, 12.4vw); }
.wordmark canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
/* the fallback holds the space until the canvas is measured; it must never wrap
   or it drives the footer to several times its real height */
.wordmark-static {
  position: absolute; inset: 0; display: flex; align-items: flex-end; justify-content: center;
  white-space: nowrap; color: var(--paper);
  font: 600 11.9vw/1 Archivo, sans-serif; letter-spacing: -.035em;
}
.wordmark.is-canvas-ready .wordmark-static { display: none; }

/* ---- reveal + motion ------------------------------------------------ */
[data-reveal] { opacity: 0; transform: translateY(10px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
[data-reveal].is-in { opacity: 1; transform: none; }


@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition-duration: 120ms !important;
    transition-property: color, background-color, border-color, opacity !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
}

@media (max-width: 620px) {
  :root { --col: calc(100% - 32px); }
  /* bottom-aligned copy leaves ~300px of dead ground above the name at this
     height, so the panel is shortened rather than padded */
  .opening { min-height: clamp(370px, 56vh, 470px); padding-top: clamp(80px, 22vw, 110px); }
  .chrome-nav a { padding: 0 8px; font-size: 12.5px; }
  .field-pair { grid-template-columns: minmax(0, 1fr); }
  .row { grid-template-columns: 34px minmax(0, 1fr); gap: 12px; }
  .tile { width: 34px; height: 34px; }
  .rows--text .row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .row-meta { grid-column: 2; justify-self: start; }
  .rows--text .row-meta { grid-column: 1; }
  /* the field reads as haze behind body copy at this width, so it is pushed back */
  .opening::after { background: linear-gradient(115deg, rgba(11, 10, 13, .95) 30%, rgba(11, 10, 13, .6) 100%); }
}

/* the honeypot is removed from layout, from sight and from the a11y tree; it
   must never be reachable by a person, only by something filling every field */
.hp { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.channel-status[data-state="ok"] { color: var(--paper); }
.btn[disabled] { opacity: .55; cursor: not-allowed; }
