/* page-kit.css
 *
 * EXTRACTED VERBATIM from landing.html on 6 September 2026 — not retyped,
 * not tidied. This is the stylesheet the front page has always used, moved
 * out so that any page built from blocks wears exactly the same clothes.
 *
 * That is what makes "the rendered page is identical to the old one"
 * provable rather than hopeful: there is only one copy of these rules and
 * both pages load it.
 *
 * It reads entirely from /theme.css. No colour is written by hand here — if
 * you need one, add a token there. Load order on every page:
 *
 *     /theme.css      the tokens (plus whatever theme is live)
 *     /page-kit.css   these rules
 *
 * Rules for a block that does not appear on a given page are simply unused;
 * the whole file is about 12KB and compresses to a few, so it is not worth
 * splitting per block and losing the guarantee above.
 */

  /* Everything here reads from /theme.css. No colour is written by hand
     on this page — if you need one, add a token there instead. */

  .wrap { max-width: 1180px; margin: 0 auto; padding: 0 20px; }

  /* ---- The gateway chamber ------------------------------------------ */
  .stage {
    position: relative; overflow: hidden;
    border-bottom: 1px solid var(--stone-cut);
    padding: 48px 0 56px;
  }
  .stage-inner {
    display: grid; grid-template-columns: minmax(0,1fr) auto;
    gap: 48px; align-items: center;
  }
  .kicker {
    font-family: var(--font-ui); font-size: 12px; font-weight: 700;
    letter-spacing: 0.24em; text-transform: uppercase; color: var(--sigil);
    margin: 0 0 14px;
  }
  .stage h1 {
    font-size: clamp(34px, 5.2vw, 62px); line-height: 1.02;
    margin: 0 0 18px; color: var(--text); text-shadow: 0 2px 14px rgba(0,0,0,0.6);
  }
  .stage h1 em { font-style: normal; color: var(--sigil); display: block; }
  .lede {
    font-family: var(--font-ui); font-size: 17px; line-height: 1.6;
    color: var(--muted); max-width: 52ch; margin: 0;
  }
  .stage-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
  .readout {
    display: flex; flex-wrap: wrap; gap: 6px 22px; margin-top: 26px;
    font-family: var(--font-data); font-size: 12px; letter-spacing: 0.08em;
    color: var(--dim); text-transform: uppercase;
  }
  .readout b { color: var(--muted); font-weight: 700; }

  /* ---- Buttons ------------------------------------------------------
     The corner-bracket button, recoloured per use by --edge. */
  .btn {
    --edge: var(--sigil-deep);
    position: relative; display: inline-flex; align-items: center; gap: 9px;
    min-height: 44px; padding: 0 22px; cursor: pointer; text-decoration: none;
    font-family: var(--font-ui); font-weight: 700; font-size: 12.5px;
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--text);
    background: linear-gradient(180deg, color-mix(in srgb, var(--edge) 14%, var(--stone)), var(--void));
    border: 1px solid color-mix(in srgb, var(--edge) 60%, transparent);
    border-radius: 3px;
    transition: transform var(--speed), box-shadow var(--speed), border-color var(--speed);
  }
  .btn::before, .btn::after { content: ""; position: absolute; width: 8px; height: 8px; border-color: var(--edge); }
  .btn::before { left: 4px; top: 4px; border-left: 2px solid; border-top: 2px solid; }
  .btn::after { right: 4px; bottom: 4px; border-right: 2px solid; border-bottom: 2px solid; }
  .btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 0 calc(26px * var(--glow)) color-mix(in srgb, var(--edge) 34%, transparent);
  }
  .btn:active { transform: translateY(1px); }
  .btn-quiet { --edge: var(--stone-cut); color: var(--muted); }
  .btn-aether { --edge: var(--aether); }

  /* ---- The gate -----------------------------------------------------
     Seven layers, each independent. Switch one off by deleting its
     element — nothing else depends on it. New layers get added the same
     way, which is the whole point of building it like this. */
  .gate { position: relative; width: clamp(260px, 34vw, 400px); aspect-ratio: 1; flex: none; }
  .gate-layer { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; }

  .l-halo {
    inset: -16%;
    background: radial-gradient(circle, color-mix(in srgb, var(--aether) calc(22% * var(--glow)), transparent) 0%, transparent 58%);
    animation: breathe 7s ease-in-out infinite;
  }
  @keyframes breathe { 0%,100% { opacity: .7; transform: scale(1); } 50% { opacity: 1; transform: scale(1.04); } }

  .l-stone {
    border: clamp(20px, 2.9vw, 34px) solid transparent;
    background:
      linear-gradient(var(--stone), var(--stone)) padding-box,
      conic-gradient(from 200deg, var(--stone-cut) 0deg, var(--stone-lit) 55deg, var(--stone) 130deg,
        var(--stone-cut) 200deg, var(--stone-lit) 265deg, var(--stone) 330deg, var(--stone-cut) 360deg) border-box;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.75), 0 24px 70px rgba(0,0,0,0.6);
  }
  .l-stone::after {
    content: ""; position: absolute; inset: -1px; border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--sigil) 22%, transparent);
  }

  .l-ticks {
    inset: clamp(22px, 3.1vw, 37px);
    background: repeating-conic-gradient(from 0deg,
      color-mix(in srgb, var(--aether) 40%, transparent) 0deg 0.5deg, transparent 0.5deg 5deg);
    -webkit-mask: radial-gradient(circle, transparent 0 76%, #000 76.5% 100%);
            mask: radial-gradient(circle, transparent 0 76%, #000 76.5% 100%);
    animation: spin 90s linear infinite; opacity: .65;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  @keyframes spinback { to { transform: rotate(-360deg); } }

  .l-glyphs { inset: clamp(34px, 4.6vw, 56px); animation: spinback 150s linear infinite; }
  /* Placed by layoutGlyphs() in JS, for the same reason the housings are:
     a percentage translate here resolves against the GLYPH's own box, which
     is a few pixels wide, so they all end up in a heap in the middle. The
     radius has to come from the ring's measured size. */
  .glyph {
    position: absolute; left: 50%; top: 50%;
    font-family: var(--font-display); font-size: 13px; font-weight: 700;
    color: color-mix(in srgb, var(--sigil) 80%, transparent);
    text-shadow: 0 0 10px color-mix(in srgb, var(--sigil) 45%, transparent);
  }

  .l-energy {
    inset: clamp(48px, 6.2vw, 75px);
    border: 2px solid color-mix(in srgb, var(--aether) 85%, transparent);
    box-shadow: 0 0 calc(24px * var(--glow)) color-mix(in srgb, var(--aether) 50%, transparent),
                inset 0 0 calc(30px * var(--glow)) color-mix(in srgb, var(--aether) 24%, transparent);
    animation: pulse 3.4s ease-in-out infinite;
  }
  @keyframes pulse { 0%,100% { opacity: .75; } 50% { opacity: 1; } }

  .l-aperture { inset: clamp(50px, 6.5vw, 78px); overflow: hidden; }
  .l-aperture canvas { width: 100%; height: 100%; display: block; }

  .housing {
    position: absolute; left: 50%; top: 50%; width: 19px; height: 30px;
    background: linear-gradient(180deg, var(--stone-lit), var(--void));
    border: 1px solid var(--stone-cut); border-radius: 2px;
    transition: box-shadow var(--speed), border-color var(--speed);
  }
  .housing::after {
    content: ""; position: absolute; inset: 4px 5px; border-radius: 1px;
    background: var(--stone); transition: background var(--speed), box-shadow var(--speed);
  }
  .housing.lit { border-color: color-mix(in srgb, var(--sigil) 80%, transparent); }
  .housing.lit::after {
    background: var(--sigil);
    box-shadow: 0 0 13px var(--sigil), 0 0 28px color-mix(in srgb, var(--sigil) 55%, transparent);
  }
  /* A pilot light while the gate is asleep — off, not broken. */
  .housing.pilot::after {
    background: color-mix(in srgb, var(--sigil) 45%, var(--stone));
    box-shadow: 0 0 11px color-mix(in srgb, var(--sigil) 38%, transparent);
  }

  .gate-caption {
    position: absolute; left: 50%; top: calc(100% + 12px); transform: translateX(-50%);
    white-space: nowrap; font-family: var(--font-data); font-size: 11.5px;
    letter-spacing: 0.2em; text-transform: uppercase; color: var(--dim);
  }
  .gate-caption b { color: var(--aether); font-weight: 700; }

  /* ---- Dormant: the machine asleep, for anyone not signed in -------- */
  body.is-guest .l-halo { opacity: .2; animation: none;
    background: radial-gradient(circle, color-mix(in srgb, var(--dim) 16%, transparent), transparent 55%); }
  body.is-guest .l-stone { filter: saturate(.2) brightness(.62); }
  body.is-guest .l-ticks { opacity: .12; filter: grayscale(1); }
  body.is-guest .glyph { color: var(--dim); text-shadow: none; opacity: .55; }
  body.is-guest .l-energy {
    border-color: color-mix(in srgb, var(--dim) 55%, transparent);
    box-shadow: none; animation: none; opacity: .45;
  }
  body.is-guest .l-aperture canvas { opacity: .12; filter: grayscale(.85); }
  body.is-guest .gate-caption b { color: var(--dim); }

  /* ---- Which half of the page shows -------------------------------- */
  /* Guest is the default so it holds before /api/me has answered. */
  body:not(.is-guest) .only-guest { display: none; }
  body.is-guest .only-member { display: none; }

  /* ---- Sign-in slot ------------------------------------------------- */
  #signInSlot { margin-top: 24px; }
  #signInSlot .shared-signin-banner { border-radius: var(--radius-sm); }
  .signin-note { font-family: var(--font-ui); font-size: 13px; color: var(--dim); margin: 10px 0 0; }

  /* ---- Destination plates ------------------------------------------- */
  .rail { padding: 34px 0 0; }
  .rail h2 {
    font-size: 18px; letter-spacing: 0.05em; color: var(--sigil); margin: 0 0 14px;
  }
  .plates { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; }
  .plate {
    display: block; padding: 15px 17px; text-decoration: none;
    background: var(--panel-bg); border: 1px solid var(--stone-cut);
    border-radius: var(--radius); transition: border-color var(--speed), transform var(--speed);
  }
  .plate:hover { border-color: var(--sigil-deep); transform: translateY(-2px); }
  .plate-name { font-family: var(--font-display); font-size: 17px; color: var(--text); margin: 0 0 4px; }
  .plate-meta {
    font-family: var(--font-data); font-size: 11px; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--dim);
  }
  .plate-meta .dot {
    display: inline-block; width: 7px; height: 7px; border-radius: 50%;
    background: var(--live); box-shadow: 0 0 8px var(--live); margin-right: 6px;
  }

  /* ---- What's here -------------------------------------------------- */
  .section { padding: 56px 0; }
  .section-head { max-width: 60ch; margin-bottom: 28px; }
  .section-head h2 { font-size: clamp(24px, 3.2vw, 34px); color: var(--text); margin: 0 0 12px; }
  .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
  .card {
    padding: 20px 22px; background: var(--panel-bg);
    border: 1px solid var(--stone-cut); border-radius: var(--radius);
  }
  .card h3 {
    font-family: var(--font-data); font-size: 11.5px; letter-spacing: 0.2em;
    text-transform: uppercase; color: var(--sigil); margin: 0 0 10px; font-weight: 700;
  }
  .card p { font-family: var(--font-ui); font-size: 14.5px; line-height: 1.6; color: var(--muted); margin: 0; }
  .card a { color: var(--sigil); }

  .honest {
    margin-top: 34px; padding: 18px 22px; border-left: 3px solid var(--sigil-deep);
    background: var(--panel-bg); border-radius: 0 var(--radius) var(--radius) 0;
  }
  .honest p { font-family: var(--font-ui); font-size: 14.5px; line-height: 1.65; color: var(--muted); margin: 0; }

  /* ---- Sound toggle -------------------------------------------------- */
  .sound {
    display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    font-family: var(--font-data); font-size: 11px; letter-spacing: 0.16em;
    text-transform: uppercase; color: var(--dim);
    background: transparent; border: 1px solid var(--stone-cut);
    border-radius: 3px; padding: 7px 12px; transition: var(--speed);
  }
  .sound[aria-pressed="true"] { color: var(--aether); border-color: color-mix(in srgb, var(--aether) 55%, transparent); }

  @media (max-width: 900px) {
    .stage-inner { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 34px; }
    .lede { max-width: 46ch; }
    .stage-actions, .readout { justify-content: center; }
    /* The caption is absolutely positioned below the ring, so once the
       gate moves above the copy it needs room reserved or it lands on
       top of the headline. */
    .gate { order: -1; width: min(70vw, 300px); margin-bottom: 30px; }
  }
  @media (max-width: 600px) {
    .stage { padding: 30px 0 40px; }
    .section { padding: 40px 0; }
  }

/* =====================================================================
   BLOCK TYPES THAT ARE NOT ON THE OLD FRONT PAGE
   Added 6 September 2026 with the page builder. Everything above this
   line came out of landing.html untouched; everything below is new, and
   is only ever used by a block the old page did not have — which is why
   adding it cannot change how the front page looks.
   ===================================================================== */

/* ---- Text block ---- */
.prose { max-width: 68ch; }
.prose p {
  font-family: var(--font-ui); font-size: 16px; line-height: 1.7;
  color: var(--text-soft); margin: 0 0 16px;
}
.prose p:last-child { margin-bottom: 0; }
.prose a { color: var(--sigil); }

/* ---- Picture block ----
   The mat behind a picture is deliberately the page colour rather than
   black: a screenshot of a world already has its own sky, and a black
   frame around it reads as a letterbox rather than a picture. */
.pic { margin: 0 0 22px; }
.pic:last-child { margin-bottom: 0; }
.pic img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--stone-cut); border-radius: var(--radius);
}
.pic-wide   { max-width: 900px; }
.pic-narrow { max-width: 560px; }
.pic figcaption {
  font-family: var(--font-ui); font-size: 13px; line-height: 1.55;
  color: var(--dim); margin-top: 9px;
}

/* ---- Gallery block ----
   auto-fit rather than a fixed count, so three pictures fill the row on a
   laptop and stack on a phone without a breakpoint per case. */
.gallery {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px; margin-bottom: 22px;
}
.gallery img {
  display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3;
  border: 1px solid var(--stone-cut); border-radius: var(--radius);
}

/* Blocks stack inside one section, so anything that follows a card grid or
   a heading needs its own breathing room rather than relying on the one
   .honest margin the old page happened to have. */
.section .cards + .cards,
.section .cards + .prose,
.section .prose + .cards,
.section .prose + .prose,
.section .cards + .gallery,
.section .prose + .gallery,
.section .gallery + .prose { margin-top: 22px; }

/* ---- Video block ----
   The wrapper keeps a 16:9 box so the page does not jump when the embed
   finally loads. aspect-ratio does this on its own now; the old
   padding-bottom trick is not needed and would fight it. */
.video { margin: 0 0 22px; max-width: 900px; }
.video:last-child { margin-bottom: 0; }
.video-frame {
  aspect-ratio: 16 / 9; background: var(--void-deep);
  border: 1px solid var(--stone-cut); border-radius: var(--radius); overflow: hidden;
}
.video-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.video figcaption {
  font-family: var(--font-ui); font-size: 13px; line-height: 1.55;
  color: var(--dim); margin-top: 9px;
}

/* ---- Space block ---- */
.spacer-small  { height: 16px; }
.spacer-medium { height: 36px; }
.spacer-large  { height: 72px; }
