/* ============================================================
   ViberSpace — contact surface. "Two-Chute Sort".

   The page is a sorter, not an inbox. One question — do you hold
   an invitation — is the H1, and the fork drawn beneath it splits
   into exactly two desks: request at left, sign-in at right. The
   request desk records and sends for real, and once a record
   exists it takes the world's stamped field and live notch,
   because there is now something behind it.

   Surface-only. The world lives in sheet_core.css.
   ============================================================ */

/* ---------- The question ---------- */
.sort{ padding-top:clamp(22px,2.6vw,36px); scroll-margin-top:84px }

/* Centred because the composition is symmetric: the headline is the mouth of
   the fork, and both desks hang off it evenly. Nothing else on this surface
   centres. */
.sort-head{ text-align:center }
.sort-head h1{ margin-bottom:16px }
/* The question has to carry the viewport, so its sub-clause steps down instead
   of matching it line for line — at display size the longer second line reads
   louder than the question it answers to. Set as a fraction of the question so
   it tracks the H1's own clamp: headline rank beside the display, title rank
   once the display re-clamps on a phone. */
.sort-head h1 .thin{
  margin-top:12px;
  font-size:.46em; letter-spacing:-0.01em;
}
.sort-head .lede{ margin:0 auto 26px; text-wrap:balance }

/* ---------- The fork ----------
   The sort, drawn. Hairlines stay exactly 1px at any width because the paths
   carry non-scaling-stroke, which is what lets the diagram span the container
   at a fixed height instead of a fixed aspect ratio — so the two arrows land
   on the two desks below at every viewport. */
.fork{ margin-top:clamp(14px,1.8vw,22px) }
.fork svg{ display:block; width:100%; height:100px }

/* ---------- The two desks ---------- */
/* Each desk is as long as it has business being: the sort feeds two documents,
   not two columns that have to end together. */
.chutes{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--gap); align-items:start;
}
.chute .face{ padding:0; display:flex; flex-direction:column }

/* The head states the answer that routed you here. The answer sits on the
   heading line in full ink, as the section letter does on the about sheet —
   it is the information, not a label above it. */
/* The bar and its referent — the routing answer this desk is keyed to — are the
   world's .dhead device, in sheet_core.css. This desk states no delta; the
   class remains so the receipt can promote its own hairline below. */

.chute-body{
  flex:1; display:flex; flex-direction:column;
  padding:clamp(16px,1.9vw,22px) 20px clamp(20px,2.4vw,28px);
}
.chute-note{
  margin:clamp(14px,1.8vw,20px) 0 0; max-width:56ch;
  font-size:12.5px; line-height:1.7; color:var(--ink-2);
}
.chute .spec{ font-size:13px }
.chute .spec dt{ letter-spacing:.1em }
/* What the desk makes, stated before the form is filled in — the fact the two
   labelled fields below cannot show, and the one the receipt prints back, so
   the empty desk and the earned one read as one object in two states. */
.desk-spec{ margin-bottom:clamp(16px,1.9vw,20px); padding-bottom:clamp(12px,1.5vw,15px); border-bottom:1px solid var(--mountain) }

/* An address is whatever length the reader's is; it wraps inside the panel
   rather than running out of it. */
.chute--done .spec dd{ white-space:normal; overflow-wrap:anywhere }
/* Focus is moved to the record after the redirect. The ring answers to :focus
   as well as :focus-visible, because a container focused in code is not a
   :focus-visible match — and it is drawn on the wrapper, because the panel's
   own clip path would cut the outline off. */
.receipt-focus:focus,
.receipt-focus:focus-visible{ outline:2px solid var(--valley-ink); outline-offset:3px }

.chute--in .btn-edge{ align-self:flex-start; margin-top:clamp(18px,2.4vw,26px) }

.chute--request .req{ margin:0 }
.chute--request .gate{ margin-top:clamp(16px,2vw,22px) }

/* Once the request exists it is a record, so the desk takes the world's
   stamped field under its live notch — the same treatment an about answer
   earns by having something behind it. */
.chute--done{ --panel-face:var(--foil-wash) }
.chute--done .chute-head{ border-bottom-color:var(--rule) }

/* ---------- The third path ---------- */
.open .face{ padding:0 }
.chan{
  display:flex; align-items:center; gap:13px;
  padding:15px 20px; text-decoration:none; color:var(--ink);
  transition:background .18s var(--ease);
}
.chan:hover{ background:var(--sheet-2) }
.chan-mark{ width:20px; height:20px; flex:0 0 auto; color:var(--ink-2) }
.chan:hover .chan-mark{ color:var(--ink) }
.chan-n{
  font:700 12px/1.4 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  flex:0 1 auto; min-width:0;
}
.chan .dots{ flex:1 1 auto; min-width:24px; border-bottom:1px dotted var(--mountain); transform:translateY(-3px) }
.chan-v{ font:700 12.5px/1.4 var(--mono); color:var(--valley-ink); white-space:nowrap; flex:0 0 auto }
.chan-note{
  margin:0; padding:0 20px 17px; max-width:60ch;
  font-size:12.5px; line-height:1.7; color:var(--ink-2);
}

/* ---------- What happens to it ---------- */
.handling .face{ padding:clamp(22px,3vw,38px) }
.handling .head{ margin-bottom:clamp(18px,2.4vw,26px) }
.handling-grid{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(22px,3.4vw,48px); align-items:start;
}
.handling-grid .spec{ font-size:13px }
.handling-grid p{ margin:0; max-width:60ch; font-size:15px; line-height:1.75; color:var(--ink-2) }

/* ---------- The one authored moment ----------
   The sort draws itself on arrival: the stem, then both legs together, then
   each arrowhead seats from the line that reached it.

   The fork above is its own rest state — drawn, whole, no animation. The zero
   state is armed by fork_controller.js only when the draw can actually run,
   so a reader without JavaScript, with reduced motion, or on a renderer that
   never plays the animation still gets the diagram the page is about. */
.fork.is-armed .stem,
.fork.is-armed .leg{ stroke-dasharray:100; stroke-dashoffset:100 }
.fork.is-armed .tip{ transform:scale(0); transform-box:fill-box; transform-origin:50% 0 }

.fork.is-armed.is-drawn .stem{ animation:fork-draw .34s var(--ease) forwards }
.fork.is-armed.is-drawn .leg{ animation:fork-draw .8s var(--ease) forwards; animation-delay:.26s }
.fork.is-armed.is-drawn .tip{ animation:tip-seat .38s var(--ease) forwards; animation-delay:.98s }

@keyframes fork-draw{ to{ stroke-dashoffset:0 } }
@keyframes tip-seat{ to{ transform:scale(1) } }

/* ---------- Adaptation ---------- */
@media (max-width:1080px){
  .fork svg{ height:92px }
  .handling-grid{ grid-template-columns:1fr; gap:24px }
}

@media (max-width:760px){
  /* The desks stack, so a fork drawn across two columns would point at
     nothing. The answers it carried are already on the desk heads, which is
     where the sort survives at this width. */
  .fork{ display:none }
  .chutes{ grid-template-columns:1fr }
  /* The centring existed to hold the fork's symmetry. With the fork gone, the
     head reads better ranged left, like every other surface in this world. */
  .sort-head{ text-align:left }
  .sort-head .lede{ margin-inline:0 }
}

@media (max-width:520px){
  .chute-head,
  .chute-body,
  .chan,
  .chan-note{ padding-inline:15px }
  /* A leader running to the edge with its value wrapped beneath ties nothing
     to anything, so the value is carried to the edge by the name itself. */
  .chan{ flex-wrap:wrap; row-gap:7px }
  .chan .dots{ display:none }
  .chan-v{ margin-left:auto }
  /* Same reasoning as the channel row, and the same treatment the documentation
     surface already uses at its own narrow width: a leader squeezed to nothing
     beside a value that had to wrap ties nothing to anything. The term goes
     above its value, every pair the same way — a value right-aligned under a
     wrapped row lands nearer the next term than its own. */
  .chute .spec div,
  .handling .spec div{ display:block }
  .chute .spec .dots,
  .handling .spec .dots{ display:none }
  .chute .spec dd,
  .handling .spec dd{ white-space:normal; margin-left:0; text-align:left; margin-top:1px }
  .chute .spec div + div,
  .handling .spec div + div{ margin-top:10px }
}
