:root{
  --ink:#F6F3ED;
  --ink-soft:#D7D2C9;
  --bg:#15170F;
  --bg-deep:#0A0B08;
  --accent-lit:#FF7A55;
  /* Reserved privacy link color, canon 2026-08-26. Nothing else uses it. */
  --rk-privacy:#c7b6f5;
  --hand:'Patrick Hand','Instrument Sans','Helvetica Neue',Helvetica,Arial,sans-serif;
  --sans:'Instrument Sans','Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,Menlo,Consolas,monospace;
  --pad:clamp(20px,4vw,56px);
}
*{box-sizing:border-box}
html,body{margin:0;min-height:100%;background:var(--bg);color:var(--ink)}
body{font-family:var(--sans);-webkit-font-smoothing:antialiased}
a{color:var(--accent-lit);text-decoration:none}
a:focus-visible{outline:2px solid var(--accent-lit);outline-offset:3px;border-radius:3px}
.skip{position:absolute;left:-999px;top:8px;padding:8px 12px;background:var(--bg-deep);color:var(--ink);font-family:var(--mono);font-size:12px;border:1px solid var(--accent-lit);border-radius:8px;z-index:10}
.skip:focus{left:8px}
.hero{position:relative;min-height:100svh;overflow:hidden;background:var(--bg)}
.hero-layer{position:absolute;inset:0;pointer-events:none}
.hero-photo{background-size:cover;background-position:center}
/* Backdrop artwork switch: rk_fa11back (fallback) is this site's default;
   rk_defau1t (default) is the alternative. html[data-backdrop] flips which artwork
   paints; a header toggle writes the attribute and persists the choice in
   localStorage rk-backdrop (see backdrop-toggle.js). The veil is unchanged by
   the artwork that sits under it. The canon grid and edge glow are NOT
   painted over the fallback artwork: it carries its own purple glow ramp, so
   the orange grid lines and orange edge glow are hidden under
   html[data-backdrop="fallback"] (see below). Default is unchanged. */
html[data-backdrop="default"] .hero-photo{background-image:url(/assets/bg.png);background-image:image-set(url(/assets/bg.webp) type("image/webp"),url(/assets/bg.png) type("image/png"))}
html[data-backdrop="fallback"] .hero-photo{background-image:url(/assets/bg-fallback.png);background-image:image-set(url(/assets/bg-fallback.webp) type("image/webp"),url(/assets/bg-fallback.png) type("image/png"))}
/* Canon backdrop darkening (rk_branding/canon/site-canon.md). */
.hero-veil{background:linear-gradient(180deg,rgba(8,9,7,.72),rgba(8,9,7,.94))}
/* Canon grid: orange 58x42 at .18/.14, fading out toward the top. Replaces
   the white 40x40 grid and its top-anchored mask. */
.hero-grid{
  background-image:
    repeating-linear-gradient(90deg,rgba(255,124,72,.18) 0 1px,transparent 1px 58px),
    repeating-linear-gradient(0deg,rgba(255,124,72,.14) 0 1px,transparent 1px 42px);
  -webkit-mask-image:linear-gradient(0deg,#000 0%,rgba(0,0,0,.86) 18%,rgba(0,0,0,.34) 46%,transparent 72%);
  mask-image:linear-gradient(0deg,#000 0%,rgba(0,0,0,.86) 18%,rgba(0,0,0,.34) 46%,transparent 72%);
}
/* Canon edge glow, the ramp. rk_branding/canon/site-canon.md, ratified
   2026-08-26. One inverted radial masked to the bottom band, replacing three
   additive sources that read as three hot spots at wide viewports. The alpha
   is .24, not .4: that is what keeps the grid legible through the wider band. */
.hero-glow{
  background-image:
    radial-gradient(66% 60% at 50% 36%,transparent 89%,rgba(255,104,54,.24) 100%);
  -webkit-mask-image:linear-gradient(0deg,#000 0%,#000 22%,rgba(0,0,0,.62) 36%,rgba(0,0,0,.22) 50%,transparent 66%);
  mask-image:linear-gradient(0deg,#000 0%,#000 22%,rgba(0,0,0,.62) 36%,rgba(0,0,0,.22) 50%,transparent 66%);
}
/* Owner correction: the fallback artwork carries its own purple glow ramp.
   The canon grid and edge glow (orange) must not paint over it. The veil
   stays in both states; the default state is unchanged. */
html[data-backdrop="fallback"] .hero-grid{display:none}
html[data-backdrop="fallback"] .hero-glow{display:none}
/* Lighter veil for the fallback artwork ONLY. The canon veil above is
   unchanged and still governs the default backdrop. The fallback artwork
   carries its own purple ramp along the bottom edge, which the canon
   .72/.94 darkening buries. These stops are measured, not chosen: .60 is
   the lightest top stop at which white body text and the mono labels still
   clear 4.5:1 over the brightest band of the composited artwork at 1440
   (.59 measures 4.45 for --ink-soft). The top stop is the heavier one here
   because the artwork brightest band is the warm foliage at the top, not
   the bottom. The bottom stop stays .50 and is capped at .55: past that
   the purple ramp stops reading. scripts/check.mjs holds both. */
html[data-backdrop="fallback"] .hero-veil{background:linear-gradient(180deg,rgba(8,9,7,.60),rgba(8,9,7,.50))}
.hero-inner{position:relative;min-height:100svh;display:grid;grid-template-rows:1fr auto;padding:var(--pad)}
/* Canonical XYZ header lockup: property mark plus domain text, IBM Plex Mono
   .82rem, ink, 12px gap, 42px mark. The .engineering accent uses the shared
   engineering accent #ff7a55 (the pair has no family footer color). */
.site-header{position:absolute;inset:0 0 auto;z-index:3;display:flex;align-items:center;padding:18px 30px;pointer-events:none}
.site-brand{display:inline-flex;min-height:44px;align-items:center;gap:12px;pointer-events:auto;color:var(--ink);font-family:var(--mono);font-size:.82rem;letter-spacing:.05em}
.site-brand img{display:block;width:auto;height:42px;filter:drop-shadow(0 2px 6px rgba(0,0,0,.6))}
.site-brand:focus-visible{outline:2px solid var(--accent-lit);outline-offset:3px;border-radius:3px}
.site-tld{color:var(--accent-lit)}
/* Mirrors the app's app-bar BETA chip (_Rand0mBetaChip, per xyz #275/#286):
   borderless black scrim + white text, so it reads on any background instead
   of a brand-tinted fill that can wash out. Remove at v1. */
.beta-chip{display:inline-flex;align-items:center;margin-left:16px;padding:3px 7px;border-radius:10px;background:rgba(255,255,255,.16);color:#fff;flex-shrink:0;font:800 10px var(--mono);letter-spacing:.06em}
/* Header backdrop toggle. Sibling of the home link and of the chip, never
   inside either; it renders one lamp/theme icon plus a visually hidden mono
   label. It sits at the right, immediately before the locked sign-in
   affordance (margin-left:auto pushes it there; .locked-affordance keeps
   only a small fixed gap to its right). */
.backdrop-toggle{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;margin-left:auto;border:0;background:transparent;padding:0;border-radius:0;color:var(--ink-soft);flex-shrink:0;pointer-events:auto;cursor:pointer;opacity:.82;transition:opacity .15s ease}
.backdrop-toggle img{display:block;height:38px;width:auto}
.backdrop-toggle:hover{opacity:1}
.backdrop-toggle:focus-visible{outline:2px solid var(--accent-lit);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.backdrop-toggle{transition:none}}
.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}
.placeholder{align-self:center;justify-self:center;display:flex;flex-direction:column;align-items:center;gap:clamp(12px,2vh,20px);text-align:center;max-width:680px}
h1{margin:0;font-family:var(--hand);font-size:clamp(2.6rem,7vw,4.2rem);font-weight:400;line-height:1.08;color:var(--ink)}
#status{margin:0;font-family:var(--sans);font-size:clamp(16px,1.25vw,20px);line-height:1.5;color:var(--ink-soft)}
.privacy{max-width:680px;color:var(--ink-soft);font-size:12px;line-height:1.5;text-align:left}
.privacy summary{cursor:pointer;color:var(--rk-privacy);font-family:var(--mono);text-align:center}
.privacy p{margin:10px 0 0}
.privacy code{color:var(--ink);font-family:var(--mono)}
/* Site canon: NO top separator at all, not even a transparent one. The
   footer is set off by its padding and the edge glow. No dark grounding
   plate, no footer-local grid, no footer-local glow. isolation and overflow
   went with the pseudo-elements they existed to contain. */
.footer{position:relative;align-self:end;display:flex;justify-content:center;padding-top:clamp(10px,1.4vh,14px);margin-bottom:7vh}
.footer p{margin:0;text-align:center;font-family:var(--mono);font-size:clamp(11px,.3vw + 10px,12px);line-height:1.8;color:#F3EEE6;white-space:nowrap}
.footer .foot-domains{display:inline}
/* Canon: no resting underline on a family link. */
.footer a.foot-xyz{color:#faafa5}
.footer a.foot-llc{color:#e97862}
.footer a.foot-org{color:#f45d43}
.footer a.foot-random{color:#ff4124}
.footer a:hover,.footer a:focus-visible{color:#FFEDE6}
@media (max-width:760px) {
  .site-domain{display:none}
  /* Canon grid, tighter spacing and lower opacity under 760px. */
  .hero-grid {
    background-image:
      repeating-linear-gradient(90deg, rgba(255, 124, 72, 0.16) 0 1px, transparent 1px 46px),
      repeating-linear-gradient(0deg, rgba(255, 124, 72, 0.12) 0 1px, transparent 1px 40px);
  }
}
@media (max-width:640px){
  .site-header{padding:14px 16px}
  .site-brand img{height:34px}
  .backdrop-toggle{min-width:44px;min-height:44px}
  .hero-inner{padding:20px 10px 10px}
  .placeholder{gap:12px}
  .mark{width:clamp(180px,29vh,245px)}
  .footer p{font-size:clamp(9px,2.45vw,10px);line-height:1.4;white-space:normal}
  .footer .foot-separator{display:none}
  .footer .foot-domains{display:block}
  .footer .foot-lead,.footer .foot-domains{white-space:nowrap}
  .footer .foot-family{display:inline-flex;min-width:44px;min-height:44px;align-items:center;justify-content:center}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
/* Character art motion. The source SVGs in ruok/design/mascots declare these
   animations inline but define no keyframes, so the art is static without
   them. Shapes come from ruok/lib/widgets/mascots/mascot_motion.dart, which
   documents each track in CSS terms and test-pins its bounds, so the web and
   the app move the same way. */
@keyframes bob{0%,100%{transform:translateY(0) rotate(0deg)}50%{transform:translateY(-14px) rotate(-1.2deg)}}
@keyframes bodybob{0%,100%{transform:translateY(0) scaleY(1)}50%{transform:translateY(-5px) scaleY(.985)}}
@keyframes blink{0%,88%{transform:scaleY(1)}92%{transform:scaleY(.08)}96%,100%{transform:scaleY(1)}}
@keyframes eartwitch{0%,88%{transform:rotate(0)}90%{transform:rotate(-7deg)}94%{transform:rotate(2deg)}100%{transform:rotate(0)}}
@keyframes whisk{0%,88%{transform:rotate(0)}90%{transform:rotate(3deg)}94%{transform:rotate(-2deg)}97%{transform:rotate(1deg)}100%{transform:rotate(0)}}
@keyframes tailwave{0%,100%{transform:rotate(-2.5deg)}50%{transform:rotate(3deg)}}
@keyframes twitch{0%,78%{transform:rotate(0) translate(0,0)}82%{transform:rotate(7deg) translate(1px,-3.5px)}86%{transform:rotate(-5deg) translate(0,0)}90%{transform:rotate(4deg) translate(1px,-3.5px)}94%{transform:rotate(-2deg) translate(0,0)}100%{transform:rotate(0) translate(0,0)}}
@keyframes shadowpulse{0%,100%{transform:scale(1)}50%{transform:scale(.94)}}

/* The hero character replaces the centred logo. Transparent, so it sits on
   the canon backdrop rather than carrying one of its own. */
.hero-mascot{display:block;width:clamp(190px,31vh,330px);height:auto}

/* A reader who asked for less motion gets the first frame and nothing else. */
/* Head and pupil moves ease rather than snapping. Pointer tracking sets the
   transform attribute; this is what makes it read as a glance. */
.hero-mascot g[id]{transition:transform .15s ease-out}
@media (prefers-reduced-motion: reduce){
  .hero-mascot *{animation:none !important}
  /* No ambient motion, no easing, and mascot.js attaches no listeners at all. */
  .hero-mascot g[id]{transition:none !important}
}

/* Locked state, top right. VISUAL PLACEHOLDER ONLY: there is no auth, no
   login form, no provider wiring and no route behind this. It is not
   interactive and it is not a button, so it cannot be tabbed to or clicked.
   Intent when it is built: @rand0m.ai accounts only, and the unlocked state
   arrives once auth and the gated pages exist, at which point the random1y
   and knight1y pages migrate off ruok. None of that is built here. */
.locked-affordance{margin-left:10px;display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border:1px solid rgba(255,255,255,.14);border-radius:999px;background:rgba(255,255,255,.06);color:var(--ink-soft);font:600 11px var(--mono);letter-spacing:.04em;opacity:.72;pointer-events:none}
.locked-affordance svg{display:block;width:12px;height:12px;fill:currentColor}

/* RK PIXEL CHARACTER, shared block: byte-identical in randomly, knightly and
   org, so a change in one shows up as a diff in the other two. Everything
   between this comment and the closing marker is the shared part; per-site
   sizing and layout sit outside it.

   Two designs live in the page at once. html[data-character] picks one and
   hides the other outright, so the hidden design costs no animation. The
   default is pixel; the choice is written to localStorage as rk-character.

   The designer notes say the pixel animation is built into the SVGs. It is
   not: the three files carry no <style>, no @keyframes and no <animate>. Every
   track below is written here.
     frame toggle  f0 (rest) and f1 (bob) alternate every 0.84s, steps(1),
                   so the pair is a 1.68s cycle. On the tree that same pair is
                   the canopy lifting 1px.
     blink         .pupil scaleY every 3.78s. It is applied to the rect INSIDE
                   the pupil group because the group itself carries the pointer
                   translate, and a CSS transform on that group would win over
                   the attribute and kill the tracking.
     reduced motion freezes on f0 and stops the blink, in CSS alone: with the
                   animations off the base rules below leave f0 visible and f1
                   hidden.
   Pixels stay square: image-rendering is pixelated and every site renders the
   20x20 grid at an integer multiple of 20px. */
html[data-character="pixel"] [data-character-design="vector"],
html[data-character="vector"] [data-character-design="pixel"]{display:none}
/* The character IS the control, so the button paints nothing of its own. */
.character-toggle{display:block;margin:0;padding:0;border:0;background:transparent;color:inherit;font:inherit;line-height:0;cursor:pointer}
.character-toggle:focus-visible{outline:2px solid var(--accent-lit);outline-offset:4px;border-radius:6px}
.pixel-mascot{display:block;flex:none;image-rendering:pixelated}
.pixel-mascot .frame-rest{opacity:1}
.pixel-mascot .frame-bob{opacity:0}
.pixel-mascot .frame{animation:rk-pixel-frame 1.68s steps(1) infinite}
.pixel-mascot .frame-bob{animation-name:rk-pixel-frame-bob}
.pixel-mascot .pupil rect{transform-box:fill-box;transform-origin:center;animation:rk-pixel-blink 3.78s steps(1) infinite}
@keyframes rk-pixel-frame{0%{opacity:1}50%{opacity:0}}
@keyframes rk-pixel-frame-bob{0%{opacity:0}50%{opacity:1}}
@keyframes rk-pixel-blink{0%{transform:scaleY(1)}94%{transform:scaleY(0)}96%{transform:scaleY(1)}}
@media (prefers-reduced-motion:reduce){.pixel-mascot .frame,.pixel-mascot .pupil rect{animation:none !important}}
/* RK PIXEL CHARACTER, shared block ends. */

/* Pixel character sizing, knightly. RK-50, and the owner's follow-up after the
   hard refresh confirmed the diagnosis: THE HERO TEXT MUST NOT MOVE WHEN THE
   DESIGN SWAPS. Only the character swaps.

   So the box is shared and the art sits inside it. --rk-character-box is the
   vector's own size, width:clamp(190px,31vh,330px) on a square 800x800
   viewBox, so the vector's rendered box IS that clamp, square. BOTH
   .character-design wrappers take that box, whichever one is on screen, and
   the hero copy below therefore starts at the same y in both states.

   Inside the box the pixel grid is 20x20 and has to land on an integer
   multiple of 20px or the cells blur however hard image-rendering works, so
   the pixel art is the largest multiple of 20px that fits the box and is
   centred in it. Where CSS round() is supported that is one declaration. The
   ladder above it is the fallback, the same function sampled at each 20px
   step: 31vh reaches 200px at 645.2px tall, 220px at 709.7px, 240px at
   774.2px, 260px at 838.7px, 280px at 903.2px, 300px at 967.7px and 320px at
   1032.3px, with the two clamp ends flattening it at 180px (the floor of the
   190px minimum) and 320px (the floor of the 330px maximum).

   The old rule dropped the art to 160px under 640px WIDE, which the vector
   never does: the vector clamp is viewport-height only, so this one is too.

   NOTHING design-specific may set a height or a margin on a wrapper. That is
   what would move the copy, and the guard fails on it. */
:root{--rk-character-box:clamp(190px,31vh,330px)}
.character-design{display:flex;align-items:center;justify-content:center;width:var(--rk-character-box);height:var(--rk-character-box)}
.character-design > svg{flex:none}
.pixel-mascot{width:180px;height:180px}
@media (min-height:646px){.pixel-mascot{width:200px;height:200px}}
@media (min-height:710px){.pixel-mascot{width:220px;height:220px}}
@media (min-height:775px){.pixel-mascot{width:240px;height:240px}}
@media (min-height:839px){.pixel-mascot{width:260px;height:260px}}
@media (min-height:904px){.pixel-mascot{width:280px;height:280px}}
@media (min-height:968px){.pixel-mascot{width:300px;height:300px}}
@media (min-height:1033px){.pixel-mascot{width:320px;height:320px}}
@supports (width:round(down,31vh,20px)){
  .pixel-mascot{width:round(down,var(--rk-character-box),20px);height:round(down,var(--rk-character-box),20px)}
}
