/* ============================================================
   YAFA — LA RETE
   One object. One light. One shadow. Loaded on the opening
   route only; every other page never pays for this file.
   ============================================================ */

.rete { display: grid; gap: var(--s-3); }

.rete-stage {
  position: relative;
  width: 100%;
  max-width: 620px;
  aspect-ratio: 1 / 1;
  margin: 0;
  cursor: grab;
  touch-action: none;
  outline-offset: 8px;
}
.rete-stage.is-turning { cursor: grabbing; }

/* the ground the instrument is laid on — warm stone, never
   neutral black */
.rete-ground {
  position: absolute; inset: -12%;
  background:
    radial-gradient(62% 58% at 34% 30%, rgba(255,232,196,.09), transparent 68%),
    radial-gradient(120% 100% at 50% 50%, #201D18 0%, #14120F 74%);
  pointer-events: none;
}

.rete-stage > svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* the tympan sits beneath and shows through every hole */
.rete-tympan { z-index: 1; }

/* light from behind the plate. transmitted, never emitted —
   it lands in the aperture that is under the index mark. */
.rete-lamp {
  position: absolute;
  left: 50%; top: 6.2%;
  width: 15%; aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,231,190,.92) 0%, rgba(255,214,150,.34) 46%, transparent 72%);
  z-index: 2;
  pointer-events: none;
  transition: opacity 260ms linear;
}

/* One <svg> holds both layers. The openwork is defined once in
   <defs> and referenced by the shadow and the plate through one
   mask, so a hole that dilates dilates in both. */
.rete-svg { z-index: 3; }

/* the shadow the openwork casts across the 8 mm gap. if the
   shadow is wrong the object is wrong.

   The offsets are user units of the 1000×1000 viewBox, not CSS
   pixels — 16 units is 1.6% of the plate at any size, and the
   blur beside them is in the same space. The shadow therefore
   scales with the object, which is why the phone no longer needs
   its own softer copy. */
.rete-shadow {
  transform-box: view-box;
  transform-origin: 50% 50%;
  transform: translate(16px, 22px) scale(.995);
  opacity: .52;
  pointer-events: none;
}

.rete-turn {
  position: absolute; inset: 0;
  transform-origin: 50% 50%;
  will-change: transform;
  z-index: 3;
}
.rete-turn > svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* ---- THE EIGHTEEN, FOR A SCREEN READER ---------------------
   The pointers are holes in a mask; a mask has no accessibility
   tree. These are the same eighteen destinations as real
   options the listbox can own and aria-activedescendant can
   point at. Clipped, never display:none — a hidden element
   cannot be an active descendant.
   ------------------------------------------------------------ */

.rete-options {
  position: absolute;
  width: 1px; height: 1px;
  margin: 0; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.rete-live {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* the index mark — a fixed hairline. whatever sits under it
   is selected. one selection at a time. */
.rete-index {
  position: absolute;
  left: 50%; top: -1.5%;
  width: 1px; height: 12%;
  background: linear-gradient(to bottom, rgba(226,216,196,.85), rgba(226,216,196,0));
  transform: translateX(-.5px);
  z-index: 6;
  pointer-events: none;
}
.rete-index::after {
  content: "";
  position: absolute; left: -3.5px; top: 0;
  width: 8px; height: 8px;
  border-left: 1px solid rgba(226,216,196,.8);
  border-top: 1px solid rgba(226,216,196,.8);
  transform: rotate(45deg);
  transform-origin: center;
}

/* ---- READOUT — all type lives in the flat layer ------------ */

/* The ground bleeds 12% past the stage on every side. The
   readout has to be positioned to clear that overhang —
   an unpositioned block paints under a positioned sibling,
   which is what used to swallow the alidada line. */
.rete-readout {
  position: relative;
  z-index: 7;
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: var(--s-2) var(--s-4);
  align-items: end;
  max-width: 620px;
  padding-top: 15px;
  border-top: 1px solid rgba(226,216,196,.16);
}
.rete-readout__l { display: flex; flex-direction: column; gap: 4px; }
.rete-readout .alidada { color: #C8A465; }

.rete-readout__sel {
  display: grid; gap: 5px;
  justify-items: start;
  transition: color var(--hover);
}
.rete-readout__sel .go { color: #8E877B; transition: color var(--hover); }
.rete-readout__sel:hover .go { color: #C8A465; }
.rete-readout__sel .k {
  color: #6E675C;
  letter-spacing: .16em;
}
.rete-readout__sel .v {
  font-family: var(--serif);
  font-size: clamp(17px, 1.7vw, 23px);
  font-weight: 300;
  line-height: 1.15;
  color: #E6DFD1;
  border-bottom: 1px solid rgba(200,164,101,.42);
  padding-bottom: 3px;
}
.rete-readout__sel:hover .v { border-bottom-color: #C8A465; }

/* ---- THE OPENING ROOM --------------------------------------
   The one theme change on the site. It should feel like
   walking into a different room.
   ------------------------------------------------------------ */

.room {
  background: var(--stone-2);
  color: #E6DFD1;
  padding: var(--s-6) 0 var(--s-7);
  margin-bottom: var(--s-7);
  position: relative;
  /* The ground bleeds 12% past the stage on every side. On a
     phone the stage is the full measure, so the right-hand bleed
     was pushing the document wider than the viewport and giving
     the site a horizontal scrollbar. The bleed is atmosphere
     belonging to this room: clip it at the room's own edge. */
  overflow: hidden;
}
.room::before {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(80% 60% at 22% 14%, rgba(255,231,190,.045), transparent 70%);
  pointer-events: none;
}
.room > * { position: relative; }

.room .mono   { color: #8E877B; }
.room .faint  { color: #6E675C; }
.room .quiet  { color: #9A9184; }

.opening-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: var(--s-5) var(--s-6);
  align-items: center;
}

/* The ground bleeds 12% past the stage. Once the grid stacks on
   a phone, that bleed lands on top of the instruction line —
   an unpositioned block always paints under a positioned
   sibling. The copy has to be in the positioned layer too. */
.opening-copy { position: relative; z-index: 2; }

.opening-thesis {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(30px, 4.2vw, 62px);
  line-height: 1.05;
  letter-spacing: -.02em;
  color: #EFE9DC;
  max-width: 15ch;
}
.opening-sub {
  margin-top: var(--s-3);
  max-width: 40ch;
  color: #A79E90;
  font-size: 15px;
  line-height: 1.62;
}
.opening-instruction {
  margin-top: var(--s-4);
  display: flex; align-items: center; gap: 12px;
}
.opening-instruction i {
  display: block; width: 26px; height: 1px; background: #C8A465; opacity: .7;
}

@media (max-width: 900px) {
  .opening-grid { grid-template-columns: minmax(0,1fr); gap: var(--s-4); }
  .rete-stage { max-width: 100%; margin: 0 auto; }
  /* `margin: 0 auto` on a grid item makes it fit-content and
     centres it — which shrank the readout to a 173px column
     floating in the middle of the phone. The readout is a
     caption: it starts at the measure, like every other line. */
  .rete-readout { grid-template-columns: 1fr; gap: 10px; margin: 0; }
  .rete-readout__sel { text-align: left; padding: 0; }
  /* depth reduced: the object is held closer to the tympan on a
     small screen. The blur needs no adjustment — it is in user
     units and already scaled with the plate. */
  .rete-shadow { opacity: .46; transform: translate(10px, 14px) scale(.997); }
}

@media (prefers-reduced-motion: reduce) {
  .rete-turn { transition: none !important; }
  .rete-stage { cursor: default; }
}
