/* rift.css — THE RIFT SITE THEME.
   =========================================================================
   A whole-site look, selected by one manifest key: `web.site.theme`.
   Loaded after terminal.css (the house look) and soundchrome.css, before the
   owner's own overlay. See assemble.py::site_theme for the switch, and
   instrument.css / fracture.css / passage.css / signal.css / hatch.css for
   the five themes this one sits beside.

   WHY IT EXISTS (Paths of Pangea, 2026-08-23, Ishaq's own words): "lets
   redesign paths of pangea completely. the website full redesign. for
   website put the background in the website itself and for the logo put it
   next to the name on the top left. full redesign website so it looks very
   bad ass, not like other servers, unique, advanced and professional."

   Two of those are placements and both are answered by data rather than by
   this sheet - the mark already sits beside the name in chrome.html's brand
   lockup, and `theme.art.background` already reaches the page as
   --art-background. The rest is a look, and a look on this fleet is a NAMED
   THEME in the shared tree, never a per-owner copy of the frontend.

   DIRECTION CONTRACT (the one this sheet is audited against)
   ---------------------------------------------------------------------------
   THESIS: the page is a CONTINENT SPLITTING. Pangea did not fade apart, it
     cracked, and the owner's own artwork is that crack photographed - a black
     plate with molten filaments running through it at one insistent diagonal.
     So the site is not a document with a picture behind it; it is a core
     sample of that plate, read top to bottom.
   OWN-WORLD - the six things that are this theme and not one of the other
   five, each written so a reviewer can check it in a screenshot:
     1. THE FAULT IS THE SPINE. One continuous vertical seam runs the whole
        document in its own left track, from directly beneath the mark in the
        masthead to the footer. Every region hangs off it by a short
        horizontal tick. Nothing else in the fleet has a spine; instrument
        rules a tab bar across the top, fracture and passage centre a
        measure, signal frames each panel on its own, hatch stacks one
        column. A spine is a different SHAPE of page, which is what "not like
        other servers" asks for.
     2. THE SLAB IS SHEARED, NEVER ROUNDED. Radius is zero everywhere and
        every plate is cut once, on the top-right, at the artwork's own
        angle. One cut, not two: fracture already cuts opposite corners and
        two cuts read as a label, one reads as a fracture plane.
     3. FIGURES ARE MONUMENTS, WORDS ARE SMALL. A player count is set in the
        display face at up to 72px with its name above it as a 10px tracked
        mono line. Body copy never grows past 15px. The page's whole size
        contrast is spent on numbers and headings.
     4. ONE PICTURE, AND IT IS THE GROUND. The owner's backdrop plate is the
        only image on the site above lockup size - no hero art, no banner, no
        second plate anywhere. It is 67% pure black with a 99.9th-percentile
        luminance of 54, so it cannot wash out body copy, and the veils that
        defend text on a BRIGHT plate are opened up here rather than
        inherited: see section 2 for the arithmetic. The picture is present on
        every screen of the page instead of being switched off below the fold.
        ★ This is a RULING, not a preference. Round one of this theme put the
        owner's logo plate in the hero at full bleed and kept his backdrop as
        the ground; he read it back as "the oteher background is still on the
        website dude ... just use the background I provided." A logo plate
        stops being a mark the moment it is bigger than a lockup. A theme
        wearing `rift` sets `theme.hero_banner: false`.
     5. ONE EMBER, THREE HEATS, AND STATE IS CARRIED BY LIGHTNESS. Ember for
        the fault and the brand, hot ember for a live edge, and the ok/bad
        pair separated by luminance and by shape rather than by hue - which is
        the only separation that survives a red brand (see section 1).
     6. CONTROLS ARE CUT SLABS. A committing control is a filled ember slab
        with its trailing edge sheared off; everything else is a hairline with
        an ember cap on its leading edge. No pill, no rounding, no outline
        button that looks like a disabled one.
   MOTION: CSS first and complete without it - the fault glows, a slab lifts
     one pixel and lights its tick on hover, and the ember travels down the
     seam. js/rift.js adds ONE thing on top (the region the reader is in
     lights its own segment of the fault) and the page is finished if it never
     loads, because every segment ships LIT and the script only dims the ones
     you are not reading. Every animation is transform / opacity / filter and
     every one of them stops under prefers-reduced-motion.
   FIRST VIEWPORT: the mark and the name, the fault descending out of them,
     the plate at full strength, one headline and one control. Nothing else -
     the second screen is where the live board is, and it is full-bleed so the
     first scroll lands on an instrument rather than on more page.
   FINISH: unreviewed and undocumented is unfinished.

   ★★★★★ THE GROUND CARRIES NO RULED GEOMETRY. The owner of the house look
   rejected a ruled background twice, and test_house_look.py::TheGroundIsNever
   Ruled enforces it on html, body, main, .night and :root - INCLUDING their
   pseudo-elements. That is why the fault's tick ruler is drawn on the
   SECTIONS rather than on `main`, which was the obvious first draft and is a
   test failure. Tiled geometry inside an object is fine; on the ground it is
   graph paper.

   ★★★★★ WHY IT IS SAFE FOR EVERY OTHER OWNER. The three guards every site
   theme stands on: the file is not COPIED to a box unless that owner typed
   the key (assemble.py's `sheets` set); it is not LINKED unless it was
   copied; and every rule is scoped to [data-site-theme="rift"], which
   assemble.py writes onto <html> only for an owner who opted in.

   ★★★★ NO RAW COLOUR LITERALS and no hammered priority. Where the house look
   out-specifies something the SELECTOR is raised, never hammered. Local names
   are prefixed --rf; site.css's ink, edge and veil families and
   backdrop.css's atmos family are re-pointed where they already say the right
   thing.

   ★★★★★ AND NEVER WRITE A STAR AND A SLASH TOGETHER IN THIS PROSE. The line
   above used to read "--ink-(star)/--edge-" with the two characters adjacent,
   which is a comment-terminator: it closed THIS header eighty lines early,
   four lines of prose became garbage at the top level, and CSS error recovery
   swallowed the garbage plus the very next rule - the scope root, every token
   in this theme. The build was green, the sheet linked, the selector scan
   passed, and the page rendered with no headline, no fault line and no
   slabs, because every var() in the file resolved to nothing. The same two
   characters have now done this three times in this repo (site.css's main
   ramp, backdrop.css's bloom, and here). Say "family" or "prefix"; never
   quote the terminator. backdrop.css's own header carries the first telling.
   ========================================================================= */


/* -------------------------------------------------------------------------
   1. THE SCOPE ROOT — GEOMETRY, THE LADDER, THE EMBER
   html[data-site-theme=...] is (0,1,1) and beats :root (0,1,0) outright.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] {
  /* ---- geometry. A fracture plane has no fillet. Zero, not 1px: the shear
          is what softens a corner here, and a radius fighting a clip-path
          leaves a nicked edge on a non-integer device pixel ratio. ---- */
  --r: 0px;
  --r-s: 0px;
  --r-xs: 0px;
  --r-lg: 0px;
  --r-pill: 0px;

  /* ---- the measure. Wide, because this theme puts a track down the left of
          every band and the reading column must not pay for it. ---- */
  --maxw: 1280px;
  --gut: clamp(18px, 3.2vw, 44px);

  /* ---- THE FAULT'S OWN TRACK. Everything in the page is measured off this:
          the seam sits at its left edge, the ticks reach across it, and the
          content starts on its far side. ---- */
  --rf-track: clamp(26px, 4.2vw, 66px);
  --rf-seam: 1px;
  --rf-tick: 14px;

  /* ---- THE SHEAR. 26px of horizontal run against 13px of drop is 26.6deg,
          which is the angle the filaments in this owner's plate actually run
          at. Measured off the artwork, not chosen. ---- */
  --rf-cut: 26px;
  --rf-cut-y: 13px;

  /* ---- the ladder. Two faces doing two jobs: the display face is CAPS and
          FIGURES only, the ui face is every word a person reads. ---- */
  --rf-mast: clamp(46px, 9.4vw, 148px);
  --rf-h1: clamp(30px, 4.4vw, 58px);
  --rf-h2: clamp(24px, 3.1vw, 42px);
  --rf-h3: 17px;
  --rf-fig: clamp(40px, 5.4vw, 76px);
  --rf-body: 15px;
  --rf-body-lg: 16.5px;
  --rf-small: 13px;
  --rf-label: 10.5px;
  --rf-lab-track: .34em;
  --rf-mast-track: -.012em;
  --rf-measure: 58ch;

  /* ---- rhythm ---- */
  --rf-band: clamp(56px, 7vh, 96px);
  --rf-gap: 18px;
  --rf-pad: clamp(18px, 2.2vw, 28px);

  /* ---- THE EMBER, THREE HEATS. `--accent` is the crack, `--accent-hi` the
          filament inside it, and the wash is what a slab catches from it. ---- */
  --rf-ember: var(--accent);
  --rf-ember-hot: var(--accent-hi);
  --rf-ember-hair: color-mix(in srgb, var(--accent) 34%, transparent);
  --rf-ember-ghost: color-mix(in srgb, var(--accent) 13%, transparent);
  --rf-ember-halo: color-mix(in srgb, var(--accent-hi) 30%, transparent);
  --rf-ember-glow: color-mix(in srgb, var(--accent) 52%, transparent);

  /* ---- THE SLAB. Two densities: `slab` for a plate that carries a
          paragraph, `well` for one that only carries a figure and may stay
          open enough to show the artwork through it.

          ★ MIXED FROM --surface, NOT FROM --bg-deep, and that is the whole
          difference between a plate and nothing. This owner's floor is
          #050203 and his artwork is 67% pure black, so a slab made of the
          floor colour at any alpha is BLACK ON BLACK - it paints, it passes
          every test, and a reader cannot see that a card is there. --surface
          is the palette's own lift (bg walked 6% toward fg) and reads as a
          plate the moment it lands. ---- */
  --rf-slab: color-mix(in srgb, var(--surface) 94%, transparent);
  --rf-slab-lit: color-mix(in srgb, var(--surface-2) 97%, transparent);
  --rf-well: color-mix(in srgb, var(--surface) 72%, transparent);
  --rf-hair: color-mix(in srgb, var(--fg) 13%, transparent);
  --rf-hair-lit: color-mix(in srgb, var(--fg) 24%, transparent);

  /* ---- THE INK STROKE. A glyph-shaped darkening rather than a box, for the
          two paragraphs on this site that sit on artwork instead of on a
          slab (the hero lede and a section's sub-line). Ported law: defend
          text with ink, never by putting a panel over the picture. ---- */
  --rf-ink-stroke:
    0 1px 0 var(--bg-deep),
    0 0 10px color-mix(in srgb, var(--bg-deep) 92%, transparent),
    0 0 26px color-mix(in srgb, var(--bg-deep) 78%, transparent);

  /* ---- re-pointed house tokens ---- */
  --edge-lit: var(--rf-ember-hair);
  --border: var(--rf-hair);
  --border-2: var(--rf-hair-lit);
}


/* -------------------------------------------------------------------------
   2. THE PLATE AT FULL STRENGTH — AND THE ARITHMETIC THAT ALLOWS IT
   ---------------------------------------------------------------------------
   backdrop.css sets the veils for a plate whose brightest reading pixel is a
   fossil skull at rgb(230,230,230), and solves the alpha so body ink clears
   AA over THAT. This owner's plate is a different object and was measured:

       luminance percentile   1     25    50    75    95    99    99.9
       value                  0     0.9   2.2   5.5   15.7  34.3  54.0

   99.9% of the picture is at or below 54/255. Body ink here is --ink-2, a
   warm near-white whose relative luminance is .435, so over the plate's
   99.9th percentile it measures 5.7:1 WITH NO VEIL AT ALL. The 78% reading
   bed backdrop.css inherits is defending against a threat this picture does
   not contain, and the cost of it is the thing he actually asked for.

   So the veils open. They do not vanish: the top 0.1% of the plate is molten
   filament that does run bright, and a paragraph must not be allowed to land
   on one. Two answers, both structural rather than a blanket dim -
     a. every paragraph on this site sits on a SLAB (--rf-slab is 86% of the
        floor colour, which is opaque enough on its own), and
     b. the two that do not - the hero lede and a section sub-line - carry
        --rf-ink-stroke, a glyph-shaped darkening that follows the letters.
   Measured after: body ink on a slab over the brightest filament in the
   picture, 9.1:1. On the ink stroke, 6.4:1.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] {
  --atmos-read-core: color-mix(in srgb, var(--bg-deep) 66%, transparent);
  --atmos-read-mid:  color-mix(in srgb, var(--bg-deep) 40%, transparent);
  --atmos-read-soft: color-mix(in srgb, var(--bg-deep) 12%, transparent);
  --atmos-bar:       color-mix(in srgb, var(--bg-deep) 88%, transparent);
  --atmos-floor:     color-mix(in srgb, var(--bg-deep) 90%, transparent);
  --atmos-corner:    color-mix(in srgb, var(--bg-deep) 42%, transparent);
  --atmos-page-heavy: color-mix(in srgb, var(--bg-deep) 56%, transparent);
  --atmos-page-light: color-mix(in srgb, var(--bg-deep) 26%, transparent);
  --atmos-page-col:   color-mix(in srgb, var(--bg-deep) 40%, transparent);
  --veil-deep:   color-mix(in srgb, var(--bg-deep) 88%, transparent);
  --veil-strong: color-mix(in srgb, var(--bg-deep) 70%, transparent);
  --veil-mid:    color-mix(in srgb, var(--bg-deep) 44%, transparent);
  --veil-soft:   color-mix(in srgb, var(--bg-deep) 18%, transparent);
  --scrim-nav:   color-mix(in srgb, var(--bg-deep) 72%, transparent);
}

/* ★ THE PAGE RAMP, RESTATED SHALLOWER. backdrop.css closes `main` on
   --atmos-page-heavy one screen down so that a paragraph below the fold is
   never on artwork. Re-pointing the token above already opens it; this rule
   also moves the STOPS, because on this theme the first screen is the plate
   and the reader should still see it at 3000px down. The ramp is a plain
   linear gradient, not a repeat: the ground may never be ruled. */
html[data-site-theme="rift"] main {
  background-image: linear-gradient(180deg,
    transparent 0,
    transparent clamp(220px, 40vh, 520px),
    var(--atmos-page-light) clamp(520px, 78vh, 900px),
    var(--atmos-page-heavy) 100%);
}

/* ★ AND A SECOND, WARMER PLANE UNDER THE WHOLE DOCUMENT. `.night` is fixed,
   so it cannot follow the page; this one scrolls with it and puts a faint
   ember bloom behind the top of the reading column, which is what stops the
   long middle of a short page reading as a flat black field. Radial, single
   stop set - no repeat, and `main` is the ground so this is deliberately on
   `body` ... which is also ground. It lives on the FOOTER's own layer and on
   the hero instead; see sections 6 and 12. */


/* -------------------------------------------------------------------------
   3. THE FAULT — the spine that runs the whole document
   ---------------------------------------------------------------------------
   Drawn per band rather than once on `main`, for two reasons that both
   matter. The mechanical one: `main::before` is GROUND to
   test_house_look.py, and the tick ruler is a repeating gradient. The design
   one: a seam drawn once cannot know which region the reader is in, and
   lighting the reader's own segment is the theme's one scripted move.

   Each band draws its own full-height segment at the same x, so they chain
   into one unbroken line. `--rf-lit` is the segment's own heat: 1 when it is
   the region being read (or when there is no script at all, which is the
   default written here), lower when js/rift.js has dimmed it.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .hero.wrap,
html[data-site-theme="rift"] .section.wrap {
  position: relative;
  padding-inline-start: calc(var(--gut) + var(--rf-track));
  --rf-lit: 1;
}

/* the seam itself: a hairline with the ember pooling at its head */
html[data-site-theme="rift"] .hero.wrap::before,
html[data-site-theme="rift"] .section.wrap::before {
  content: "";
  position: absolute;
  left: var(--gut);
  top: 0;
  bottom: 0;
  width: var(--rf-seam);
  pointer-events: none;
  background-image: linear-gradient(180deg,
    var(--rf-ember) 0,
    var(--rf-ember-hair) 34%,
    var(--rf-ember-ghost) 100%);
  opacity: calc(.34 + .66 * var(--rf-lit));
  transition: opacity .5s ease;
}

/* the ruler: short ticks reaching out of the seam at a fixed rhythm. This IS
   a repeating gradient and it is deliberately on the SECTION, an object, not
   on the page ground - see the header. */
html[data-site-theme="rift"] .section.wrap::after {
  content: "";
  position: absolute;
  left: calc(var(--gut) + var(--rf-seam));
  top: 0;
  bottom: 0;
  width: 7px;
  pointer-events: none;
  background-image: repeating-linear-gradient(180deg,
    var(--rf-ember-hair) 0 1px,
    transparent 1px 22px);
  opacity: calc(.18 + .42 * var(--rf-lit));
  transition: opacity .5s ease;
}

/* the lamp: where a band's head meets the fault, the seam swells. Placed on
   the section head so it lands level with the eyebrow rather than at the
   band's geometric top, which is 60px of padding away from anything. */
html[data-site-theme="rift"] .section .sec-head {
  position: relative;
  margin-bottom: 30px;
}
html[data-site-theme="rift"] .section .sec-head::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--rf-track));
  top: 7px;
  width: var(--rf-tick);
  height: 2px;
  background-color: var(--rf-ember);
  box-shadow: 0 0 12px var(--rf-ember-glow);
  opacity: calc(.45 + .55 * var(--rf-lit));
  transition: opacity .5s ease, width .5s ease;
}


/* -------------------------------------------------------------------------
   4. THE MASTHEAD — the lockup the fault descends out of
   ---------------------------------------------------------------------------
   His two placements, both already in chrome.html's markup, given the weight
   the ask implies: the mark grows, the name is set in the display face at
   caps, and an ember rule stands between them so the pair reads as ONE
   lockup rather than as a picture next to some words.

   ★ AND THE BAR DOES NOT SPAN THE WINDOW. It is a slab inset from the top
   with its trailing corner sheared - the same object as every other plate on
   the page, so the chrome is made of the site's own material instead of
   being a strip laid over it.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .nav {
  border-bottom: 0;
  background-image: linear-gradient(180deg,
    var(--veil-deep) 0, var(--veil-strong) 62%, transparent 100%);
  box-shadow: none;
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
}
html[data-site-theme="rift"] .nav .nav-in {
  min-height: 74px;
  gap: 18px;
}

/* the hairline the bar closes on, cut short of the fault so the seam reads as
   passing THROUGH the bar rather than starting under it */
html[data-site-theme="rift"] .nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  pointer-events: none;
  background-image: linear-gradient(90deg,
    var(--rf-ember) 0,
    var(--rf-ember-hair) 22%,
    var(--rf-hair) 60%,
    transparent 100%);
}

html[data-site-theme="rift"] .nav .brand {
  gap: 0;
  align-items: stretch;
}
html[data-site-theme="rift"] .nav .brand img {
  width: 54px;
  height: 54px;
  align-self: center;
  filter: brightness(1.5) saturate(1.12)
          drop-shadow(0 0 14px var(--rf-ember-halo));
  transition: filter .4s ease, transform .4s ease;
}
html[data-site-theme="rift"] .nav .brand:hover img {
  filter: brightness(1.8) saturate(1.2)
          drop-shadow(0 0 22px var(--rf-ember-halo));
  transform: translateY(-1px);
}

/* the ember rule between the mark and the name — the head of the fault */
html[data-site-theme="rift"] .nav .brand .brand-txt {
  justify-content: center;
  gap: 5px;
  padding-inline-start: 15px;
  margin-inline-start: 15px;
  border-inline-start: 1px solid var(--rf-ember-hair);
}
html[data-site-theme="rift"] .nav .brand .brand-txt b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 21px;
  line-height: .96;
  letter-spacing: .014em;
  text-transform: uppercase;
  color: var(--fg);
}
html[data-site-theme="rift"] .nav .brand .brand-txt > span {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: var(--rf-lab-track);
  text-transform: uppercase;
  color: var(--rf-ember-hot);
  margin-top: 0;
}
/* the house look draws a block cursor under the lockup; a fault line is not a
   terminal, so it is removed the same way instrument.css removes it */
html[data-site-theme="rift"] .nav .brand .brand-cursor {
  display: none;
}

/* nav links: cut slabs, not tabs */
html[data-site-theme="rift"] .nav .nav-links a {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 11px 14px;
  border: 1px solid transparent;
  transition: color .22s ease, border-color .22s ease, background-color .22s ease;
}
html[data-site-theme="rift"] .nav .nav-links a:hover {
  color: var(--fg);
  background-color: var(--rf-ember-ghost);
  border-color: var(--rf-ember-hair);
}
html[data-site-theme="rift"] .nav .nav-links a[aria-current="page"] {
  color: var(--fg);
  background-color: transparent;
  border-color: var(--rf-ember-hair);
}
/* ★ THE HOUSE LOOK BRACKETS THE CURRENT PAGE - `content: "["` and `"]"` drawn
   by terminal.css - and this theme deletes that tell for the same reason
   instrument.css deletes the shell prompt: a bracketed control is SEQUENCE's
   signature and two owners wearing it read as one owner. The current page is
   marked here by the ember rail on its leading edge instead, which is the
   same mark every slab on this page carries. Emptying `content` rather than
   hiding the pseudo-element keeps the 2px rail this rule then draws. */
html[data-site-theme="rift"] .nav .nav-links a[aria-current="page"]::before {
  content: "";
  left: -1px;
  right: auto;
  top: -1px;
  bottom: -1px;
  width: 2px;
  height: auto;
  padding: 0;
  margin: 0;
  background-color: var(--rf-ember);
  box-shadow: 0 0 10px var(--rf-ember-glow);
}
html[data-site-theme="rift"] .nav .nav-links a[aria-current="page"]::after {
  content: "";
  display: none;
}

html[data-site-theme="rift"] .nav .nav-util .nav-cta,
html[data-site-theme="rift"] .nav .nav-util .nav-auth-btn {
  border-color: var(--rf-hair);
  color: var(--ink-3);
  font-family: var(--font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  font-size: 10.5px;
}
html[data-site-theme="rift"] .nav .nav-util .nav-cta:hover,
html[data-site-theme="rift"] .nav .nav-util .nav-auth-btn:hover {
  border-color: var(--rf-ember);
  color: var(--fg);
  background-color: var(--rf-ember-ghost);
}


/* -------------------------------------------------------------------------
   5. THE HERO — ONE PICTURE, AND IT IS THE GROUND
   ---------------------------------------------------------------------------
   ★★★★★ WHY THERE IS NO PICTURE ELEMENT IN HERE AT ALL. Round one gave this
   hero the owner's LOGO PLATE at full bleed and kept his backdrop plate as the
   page ground. Two full-bleed pictures on one page is two backgrounds, and he
   read it back exactly that way: "the oteher background is still on the
   website dude ... just use the background I provided." A logo plate is a
   PLATE - the moment it is larger than a lockup it stops being a mark and
   becomes wallpaper, and then it competes with the wallpaper.

   So the manifest turns `theme.hero_banner` off, which drops the whole
   `.hero-art` region from the HTML rather than hiding it, and the first screen
   is the BACKDROP PLATE with the name standing on it. That is one picture on
   the site, the one he chose, and the logo is a 54px mark in the corner where
   he asked for it.

   WHAT PAYS FOR THE MISSING PICTURE. A hero with nothing but a headline on a
   fixed background is a poster, and a poster is thin. Three things carry it
   instead, and none of them is an image:
     a. HEIGHT AND SCALE. The band is a full viewport and the name is set at up
        to 148px, so the first screen is the mark, the name and the plate and
        nothing else - which is the same discipline `hatch` uses and the
        opposite of stacking more furniture in.
     b. THE INK WELL RUNS AT THE PICTURE'S OWN ANGLE. The type sits in a
        diagonal darkening that follows the plate's 26.6deg filaments rather
        than in a rectangle, so the defence reads as part of the artwork
        instead of as a box laid over it.
     c. THE FOLD IS A CONTROL SURFACE. A hairline rail closes the band at the
        bottom with the fault crossing it, so the eye is handed to the live
        board rather than left at the end of a poster.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .hero {
  padding: 0;
  isolation: isolate;
  position: relative;
}
html[data-site-theme="rift"] .hero .hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  align-content: center;
  /* svh, not vh: on a phone `100vh` is the address-bar-hidden height, so a vh
     hero is always taller than the screen it opens on and the control is
     always below the fold on first paint. */
  min-height: clamp(520px, calc(100svh - 74px), 900px);
}

html[data-site-theme="rift"] .hero .hero-copy {
  grid-area: 1 / 1;
  z-index: 2;
  max-width: min(100%, 860px);
  padding-block: clamp(48px, 8vh, 96px);
}

/* THE INK WELL. A diagonal darkening at the plate's own angle, pinned behind
   the copy and bled out to the viewport on the left. It is a gradient and not
   a panel: the picture survives through it, which is the whole point of the
   round. Measured over the brightest filament the plate contains: body ink
   9.6:1, the mono line 8.1:1. */
html[data-site-theme="rift"] .hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  margin-inline-start: calc(
    -1 * (var(--gut) + var(--rf-track))
    - max(0px, (100vw - var(--maxw)) / 2));
  margin-inline-end: calc(
    -1 * var(--gut) - max(0px, (100vw - var(--maxw)) / 2));
  background-image:
    linear-gradient(116.6deg,
      var(--bg-deep) 0%,
      var(--atmos-read-core) 24%,
      var(--atmos-read-soft) 50%,
      transparent 72%),
    linear-gradient(180deg,
      var(--veil-strong) 0%, transparent 18%,
      transparent 76%, var(--bg-deep) 100%);
}

/* THE FOLD. The band closes on a hairline the fault crosses, so the first
   screen ends on an edge rather than trailing off. */
html[data-site-theme="rift"] .hero::after {
  content: "";
  position: absolute;
  left: calc(-1 * (var(--gut) + var(--rf-track))
    - max(0px, (100vw - var(--maxw)) / 2));
  right: calc(-1 * var(--gut) - max(0px, (100vw - var(--maxw)) / 2));
  bottom: 0;
  height: 1px;
  z-index: 2;
  pointer-events: none;
  background-image: linear-gradient(90deg,
    var(--rf-ember) 0,
    var(--rf-ember-hair) 26%,
    var(--rf-hair) 62%,
    transparent 100%);
}

/* the seam has to cross the well, so it out-orders it */
html[data-site-theme="rift"] .hero.wrap::before {
  z-index: 3;
}

html[data-site-theme="rift"] .hero .kicker {
  font-family: var(--font-mono);
  font-size: var(--rf-label);
  font-weight: 500;
  letter-spacing: var(--rf-lab-track);
  text-transform: uppercase;
  color: var(--rf-ember-hot);
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: clamp(14px, 2vh, 22px);
}
html[data-site-theme="rift"] .hero .kicker::before {
  content: "";
  width: 26px;
  height: 1px;
  background-color: var(--rf-ember);
  box-shadow: 0 0 10px var(--rf-ember-glow);
  margin: 0;
  border-radius: 0;
  flex: none;
}

/* THE MONUMENT. */
html[data-site-theme="rift"] .hero h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--rf-mast);
  line-height: .82;
  letter-spacing: var(--rf-mast-track);
  text-transform: uppercase;
  margin: 0;
  max-width: 9ch;
  /* white at the cap line walking down into the ember, so the name reads as
     lit from the fracture underneath it rather than tinted across it. */
  background-image: linear-gradient(178deg,
    var(--fg) 0%,
    var(--fg) 42%,
    var(--rf-ember-hot) 104%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  /* ★★★★★ `text-shadow` MUST NOT BE SET ON A `background-clip: text` HEADING.
     MEASURED, in Chromium, on this page: with `text-shadow: 0 8px 60px` the
     124px headline rendered 59,068 pixels above luminance 120 and PEAKED at
     rgb(203,196,195); with the shadow removed and nothing else changed it
     rendered 203,002 and peaked at 254. The engine composites the blurred
     shadow into the same pass as the clipped fill, so a dark shadow eats the
     glyph it is supposed to sit behind - and the result is not a missing
     effect, it is a headline quietly rendered at 80% ink, which reads as a
     grey wash and is invisible to every DOM assertion.
     Depth comes from `filter: drop-shadow()` instead, which runs AFTER the
     element is painted and cannot reach inside the fill. */
  text-shadow: none;
  filter: drop-shadow(0 12px 40px var(--bg-deep));
}
/* ★ THE TYPEWRITER CARET GOES. terminal.css ends the house H1 with a blinking
   block cursor; it is the third of the three terminal tells instrument.css
   deletes, and at this theme's 148px it is a red brick at the end of the
   owner's name. */
html[data-site-theme="rift"] .hero h1::after {
  content: "";
  display: none;
  animation: none;
}

html[data-site-theme="rift"] .hero .lede {
  font-family: var(--font-mono);
  font-size: var(--rf-small);
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-2);
  max-width: 34ch;
  margin-top: clamp(18px, 2.6vh, 28px);
  padding-inline-start: 14px;
  border-inline-start: 2px solid var(--rf-ember-hair);
  text-shadow: var(--rf-ink-stroke);
}

/* the rule over the control is cinema.css's; it is kept and re-voiced to the
   ember, and stopped at the copy column so it does not run out across the
   plate as a stray hairline */
html[data-site-theme="rift"] .hero .hero-cta {
  margin-top: clamp(24px, 3.4vh, 40px);
  padding-top: clamp(18px, 2.4vh, 30px);
  border-top: 1px solid var(--rf-ember-hair);
  max-width: 30ch;
  gap: 14px;
}


/* -------------------------------------------------------------------------
   6. SECTION HEADS — the eyebrow is a reading off the fault
   ------------------------------------------------------------------------- */
/* ★ `padding-block`, NOT the `padding` SHORTHAND. `padding: <band> 0` also
   sets the INLINE padding to zero, which silently deleted the section's right
   gutter - the wrap's own - and let every card run flush to the edge of the
   measure. Invisible on a wide desktop where the measure is inset anyway, and
   an overflowing card on a phone. */
html[data-site-theme="rift"] .section {
  padding-block: var(--rf-band);
}
html[data-site-theme="rift"] .section + .section {
  padding-block-start: 0;
}
html[data-site-theme="rift"] .sec-head .eyebrow {
  font-family: var(--font-mono);
  font-size: var(--rf-label);
  font-weight: 500;
  letter-spacing: var(--rf-lab-track);
  text-transform: uppercase;
  color: var(--rf-ember-hot);
  margin-bottom: 12px;
}
/* the house look draws a short rule before an eyebrow; here the fault's own
   tick already does that job, so the rule is removed rather than doubled */
html[data-site-theme="rift"] .sec-head .eyebrow::before {
  display: none;
}
html[data-site-theme="rift"] .sec-head h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--rf-h2);
  line-height: .92;
  letter-spacing: .006em;
  text-transform: uppercase;
  color: var(--fg);
  max-width: 18ch;
}
html[data-site-theme="rift"] .sec-head p {
  font-size: var(--rf-body);
  color: var(--ink-2);
  max-width: var(--rf-measure);
  margin-top: 12px;
  text-shadow: var(--rf-ink-stroke);
}


/* -------------------------------------------------------------------------
   7. THE SLAB — one cut corner, one ember rail, and a tick into the fault
   ---------------------------------------------------------------------------
   `clip-path` and a border cannot coexist (the clip cuts the border with the
   box), so the frame is drawn by a pseudo-element that carries the same clip
   and a background gradient standing in for the stroke. That is also what
   lets the leading edge be an EMBER RAIL and the other three a hairline in
   one paint.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .card,
html[data-site-theme="rift"] .feat,
html[data-site-theme="rift"] .status {
  position: relative;
  border: 0;
  border-radius: 0;
  background-color: var(--rf-slab);
  background-image: linear-gradient(180deg,
    var(--rf-ember-ghost) 0, transparent 42%);
  box-shadow: none;
  clip-path: polygon(
    0 0,
    calc(100% - var(--rf-cut)) 0,
    100% var(--rf-cut-y),
    100% 100%,
    0 100%);
  transition: background-color .3s ease, transform .3s ease;
}
/* ★ THE FRAME IS FIVE BACKGROUND LAYERS, NOT A BORDER AND NOT A CLIPPED RING.
   A border cannot survive the clip - the clip cuts the box and the border
   with it - and the obvious alternative, a ring drawn by a self-intersecting
   clip-path with an inner reverse winding, is a nonzero-fill trap: it renders
   as a solid plate in Chromium and as nothing at all elsewhere. It also cost
   this sheet its first render.

   So each edge is its own sized, positioned, non-repeating gradient layer,
   and the diagonal is a sixth layer: a hard two-stop gradient inside a box
   exactly the size of the cut, which draws a 1px line across it. Order is
   painting order, first on top. */
html[data-site-theme="rift"] .card::before,
html[data-site-theme="rift"] .feat::before,
html[data-site-theme="rift"] .status::before {
  content: "";
  /* ★ `display: block` IS LOAD-BEARING. site.css hides `.feat::before`
     outright, so inheriting its `display: none` here left every feature tile
     frameless while the identical rule on `.card` drew perfectly - a
     difference no reading of this file explains and only a computed-style
     read finds. */
  display: block;
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: 0;
  border: 0;
  background-color: transparent;
  opacity: 1;
  width: auto;
  height: auto;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--rf-ember), var(--rf-ember)),
    linear-gradient(var(--rf-hair-lit), var(--rf-hair-lit)),
    linear-gradient(var(--rf-hair-lit), var(--rf-hair-lit)),
    linear-gradient(var(--rf-hair-lit), var(--rf-hair-lit)),
    linear-gradient(to bottom left,
      transparent calc(50% - .6px), var(--rf-hair-lit) calc(50% - .6px),
      var(--rf-hair-lit) calc(50% + .6px), transparent calc(50% + .6px));
  background-position:
    left top,
    left top,
    left bottom,
    right bottom,
    right top;
  background-size:
    2px 100%,
    calc(100% - var(--rf-cut)) 1px,
    100% 1px,
    1px calc(100% - var(--rf-cut-y)),
    var(--rf-cut) var(--rf-cut-y);
}
/* the leading rail lights with the slab */
html[data-site-theme="rift"] .card:hover::before,
html[data-site-theme="rift"] .feat:hover::before,
html[data-site-theme="rift"] .status:hover::before {
  background-image:
    linear-gradient(var(--rf-ember-hot), var(--rf-ember-hot)),
    linear-gradient(var(--rf-ember-hair), var(--rf-ember-hair)),
    linear-gradient(var(--rf-ember-hair), var(--rf-ember-hair)),
    linear-gradient(var(--rf-ember-hair), var(--rf-ember-hair)),
    linear-gradient(to bottom left,
      transparent calc(50% - .6px), var(--rf-ember-hair) calc(50% - .6px),
      var(--rf-ember-hair) calc(50% + .6px), transparent calc(50% + .6px));
}
html[data-site-theme="rift"] .card > *,
html[data-site-theme="rift"] .feat > *,
html[data-site-theme="rift"] .status > * {
  position: relative;
  z-index: 1;
}

html[data-site-theme="rift"] .card,
html[data-site-theme="rift"] .status {
  padding: var(--rf-pad);
}
html[data-site-theme="rift"] .card:hover,
html[data-site-theme="rift"] .feat:hover {
  background-color: var(--rf-slab-lit);
  transform: translateY(-1px);
  border-color: transparent;
}
html[data-site-theme="rift"] .card h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--rf-h3);
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--fg);
  margin-bottom: 14px;
}
html[data-site-theme="rift"] .card p {
  font-size: var(--rf-body);
  color: var(--ink-2);
}


/* -------------------------------------------------------------------------
   8. THE LIVE BOARD — the full-bleed instrument, and the page's second monument
   ---------------------------------------------------------------------------
   The house status card is a header row and three boxed figures. Here it is
   ONE instrument running edge to edge of the viewport: a titled lip, then
   three cells divided by ember hairlines, the label ABOVE its figure in mono
   caps and the figure itself in the display face at up to 76px. That
   inversion - name small and above, number monumental and below - is the
   theme's size contract in one component.

   ★ WHY IT BREAKS THE MEASURE. Round two gave the hero up as a picture
   surface, so the first screen is a monument and nothing else. The FIRST
   SCROLL then has to land on something of the same weight; another column of
   the same width is not it. The band bleeds, its INK stays on the measure
   (the padding below re-inserts the wrap's own inset plus the fault's track,
   so the figures line up with every heading on the page), and it keeps the
   shear on its far corner so it is still made of the same material as the
   slabs.

   ★★ AND THE PADDING IS `padding-block` / `padding-inline`, NEVER `padding`.
   The bleed is bought with negative inline margins and paid back with inline
   padding; a `padding: <y> <x>` shorthand anywhere below would overwrite that
   inline value and slam every figure back to the viewport edge. It did
   exactly that in the first cut of this band.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .status {
  padding: 0;
  overflow: hidden;
  margin-inline-start: calc(
    -1 * (var(--gut) + var(--rf-track))
    - max(0px, (100vw - var(--maxw)) / 2));
  margin-inline-end: calc(
    -1 * var(--gut) - max(0px, (100vw - var(--maxw)) / 2));
}

/* ★ THE BLED BAND DROPS THE SLAB FRAME. Every other plate on this page wears a
   2px ember rail on its leading edge; on a band that starts at x=0 that rail
   is a red line down the browser's own edge and reads as a rendering fault
   rather than as a mark. The band gets a hairline top and bottom instead, and
   the ember returns as the lip's own wash. */
html[data-site-theme="rift"] .status::before {
  background-image:
    linear-gradient(var(--rf-hair-lit), var(--rf-hair-lit)),
    linear-gradient(var(--rf-hair-lit), var(--rf-hair-lit));
  background-position: left top, left bottom;
  background-size: 100% 1px, 100% 1px;
}
html[data-site-theme="rift"] .status:hover::before {
  background-image:
    linear-gradient(var(--rf-ember-hair), var(--rf-ember-hair)),
    linear-gradient(var(--rf-ember-hair), var(--rf-ember-hair));
}

/* THE INK COLUMN. One value, used by every child, so the lip, the figures and
   the note cannot drift apart: the wrap's own inset plus the fault's track. */
html[data-site-theme="rift"] .status {
  --rf-board-inset: max(
    var(--gut),
    calc((100vw - var(--maxw)) / 2 + var(--gut) + var(--rf-track)));
}

html[data-site-theme="rift"] .status .status-top {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 16px;
  padding-inline: var(--rf-board-inset);
  border-bottom: 1px solid var(--rf-hair);
  background-image: linear-gradient(90deg,
    var(--rf-ember-ghost) 0, transparent 62%);
}
html[data-site-theme="rift"] .status .status-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--fg);
}
html[data-site-theme="rift"] .status .status-src {
  margin-inline-start: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--fg-mute);
  border: 1px solid var(--rf-hair);
  padding: 4px 8px;
  border-radius: 0;
}
html[data-site-theme="rift"] .status .dot {
  border-radius: var(--r-round);
  width: 8px;
  height: 8px;
}

html[data-site-theme="rift"] .status .status-figs {
  display: grid;
  gap: 0;
  padding: 0;
}
html[data-site-theme="rift"] .status .fig {
  padding-block: clamp(22px, 3.4vw, 44px);
  padding-inline: var(--rf-pad);
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: 10px;
  position: relative;
  min-width: 0;
}
/* the first cell carries the ink column so its figure lines up with every
   heading on the page; the rest sit on the ordinary pad */
html[data-site-theme="rift"] .status .fig:first-child {
  padding-inline-start: var(--rf-board-inset);
}
html[data-site-theme="rift"] .status .fig:last-child {
  padding-inline-end: var(--rf-board-inset);
}
html[data-site-theme="rift"] .status .fig + .fig {
  border-inline-start: 1px solid var(--rf-hair);
}
html[data-site-theme="rift"] .status .fig b {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--rf-fig);
  line-height: .8;
  letter-spacing: -.005em;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 24px var(--rf-ember-halo);
}
html[data-site-theme="rift"] .status .fig span {
  font-family: var(--font-mono);
  font-size: var(--rf-label);
  font-weight: 500;
  letter-spacing: var(--rf-lab-track);
  text-transform: uppercase;
  color: var(--rf-ember-hot);
}
html[data-site-theme="rift"] .status .status-note {
  margin: 0;
  padding-block: 14px;
  padding-inline: var(--rf-board-inset);
  border-top: 1px solid var(--rf-hair);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .06em;
  color: var(--fg-mute);
}


/* -------------------------------------------------------------------------
   9. THE STEPS — a numbered descent, counted against the fault
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .steps li {
  padding-inline-start: 46px;
  padding-bottom: 22px;
  font-size: var(--rf-body);
  color: var(--ink-2);
}
html[data-site-theme="rift"] .steps li::before {
  width: 30px;
  height: 30px;
  border-radius: 0;
  border: 1px solid var(--rf-ember-hair);
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  color: var(--rf-ember-hot);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 15px;
  line-height: 28px;
  letter-spacing: 0;
  display: grid;
  place-items: center;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
html[data-site-theme="rift"] .steps li:not(:last-child)::after {
  left: 15px;
  width: 1px;
  background-color: var(--rf-ember-hair);
  background-image: none;
  opacity: .8;
}
html[data-site-theme="rift"] .steps li b {
  color: var(--fg);
  font-weight: 600;
}
html[data-site-theme="rift"] .join-hint {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: .08em;
  color: var(--fg-mute);
}


/* -------------------------------------------------------------------------
   10. THE TILES — the same slab, opened out
   ------------------------------------------------------------------------- */
/* ★ THREE ACROSS, RESTATED. The house look drops `.grid-3` to two columns at
   a breakpoint measured against the OLD 1200px measure; this theme's is 1280
   with a 66px track taken out of it, so the same breakpoint fires while there
   is still room for three - and two tiles on one row with a third orphaned
   below is the shape a reader reads as "something is missing". */
html[data-site-theme="rift"] .grid {
  gap: 2px;
}
html[data-site-theme="rift"] .grid.grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
html[data-site-theme="rift"] .feat {
  display: block;
  padding: clamp(20px, 2.4vw, 30px);
  background-color: var(--rf-well);
}
html[data-site-theme="rift"] .feat:hover {
  background-color: var(--rf-slab);
}
html[data-site-theme="rift"] .feat .feat-ico {
  width: 38px;
  height: 38px;
  border-radius: 0;
  border: 1px solid var(--rf-ember-hair);
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  color: var(--rf-ember-hot);
  display: grid;
  place-items: center;
  margin-bottom: 18px;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  transition: color .3s ease, border-color .3s ease;
}
html[data-site-theme="rift"] .feat:hover .feat-ico {
  color: var(--fg);
  border-color: var(--rf-ember);
}
html[data-site-theme="rift"] .feat .feat-ico svg {
  width: 19px;
  height: 19px;
}
html[data-site-theme="rift"] .feat h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 15.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg);
}
html[data-site-theme="rift"] .feat p {
  font-size: 14px;
  color: var(--ink-2);
  margin-top: 8px;
  line-height: 1.6;
}


/* -------------------------------------------------------------------------
   11. CONTROLS — cut slabs
   ---------------------------------------------------------------------------
   ★ WHY THE COMMITTING CONTROL IS THE EMBER AND THE DANGER CONTROL IS NOT
   TOLD APART BY HUE. On a red brand the two reds cannot be separated by
   colour — any pair that both clear the 3:1 status floor on near-black lands
   within about 1.5:1 of each other, which is arithmetic and not a bad pick
   (memory law, Frontier Prime 2026-08-13). So the split is carried by SHAPE,
   FILL and WORDS: a committing control is the only FILLED slab on a view, a
   destructive one is a filled plate that also carries its own mark element
   and the word, and the brand ember never fills anything that destroys.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .btn {
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  padding: 15px 24px;
  border: 1px solid var(--rf-hair-lit);
  background-color: transparent;
  background-image: none;
  color: var(--ink-2);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
  transition: color .24s ease, background-color .24s ease,
              border-color .24s ease, transform .24s ease;
}
html[data-site-theme="rift"] .btn:hover {
  color: var(--fg);
  border-color: var(--rf-ember);
  background-color: var(--rf-ember-ghost);
  transform: translateY(-1px);
}
html[data-site-theme="rift"] .btn-primary {
  border-color: transparent;
  background-color: var(--rf-ember);
  background-image: linear-gradient(102deg,
    var(--rf-ember) 0, var(--rf-ember-hot) 100%);
  color: var(--on-primary);
  box-shadow: 0 0 0 1px var(--rf-ember-hair), 0 14px 40px -22px var(--rf-ember-glow);
  clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%);
}
html[data-site-theme="rift"] .btn-primary:hover {
  background-color: var(--rf-ember-hot);
  background-image: linear-gradient(102deg,
    var(--rf-ember-hot) 0, var(--rf-ember) 100%);
  color: var(--on-primary);
  transform: translateY(-1px);
}
html[data-site-theme="rift"] .btn-ghost {
  background-color: transparent;
  border-color: var(--rf-hair);
}


/* -------------------------------------------------------------------------
   12. THE FOOTER — where the fault closes
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] .foot {
  margin-top: clamp(64px, 9vh, 120px);
  border-top: 1px solid var(--rf-hair);
  background-color: var(--bg-deep);
  background-image: linear-gradient(180deg,
    var(--rf-ember-ghost) 0, transparent 34%);
  box-shadow: none;
  padding: clamp(34px, 5vh, 60px) 0 34px;
}
/* ★ THE MARK GHOST GOES. site.css paints `--art-mark` at 300px in the footer
   corner with `mix-blend-mode: screen`. It is the house look's move and it is
   perfectly good - but on this owner it is the LOGO PLATE drawn at 300px, and
   the whole point of round two is that the logo appears at lockup size and
   nowhere else. One picture on this site, and it is his backdrop.
   `content: none` and not `display: none`: the pseudo-element then does not
   exist at all, so nothing downloads the mark a second time at 300px for a
   layer nobody sees. */
html[data-site-theme="rift"] .foot::before {
  content: none;
  /* belt as well as braces. `content: none` means the pseudo-element is never
     generated, so this cannot paint - but a computed-style audit still reports
     the inherited url() on it, and an audit that has to be explained is an
     audit that will be misread by the next person. Nulled outright so the
     answer to "is the logo drawn large anywhere" is a flat no. */
  background-image: none;
}
html[data-site-theme="rift"] .foot .wrap {
  position: relative;
}
/* the fault's last segment, closing into the floor */
html[data-site-theme="rift"] .foot .wrap::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(-1 * clamp(34px, 5vh, 60px));
  height: clamp(34px, 5vh, 60px);
  width: 1px;
  pointer-events: none;
  background-image: linear-gradient(180deg,
    var(--rf-ember-hair) 0, transparent 100%);
}
html[data-site-theme="rift"] .foot .foot-brand img {
  width: 44px;
  height: 44px;
  border-radius: 0;
  filter: brightness(1.4) saturate(1.1);
}
html[data-site-theme="rift"] .foot .foot-brand b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 17px;
  letter-spacing: .05em;
  text-transform: uppercase;
}
html[data-site-theme="rift"] .foot .foot-brand span {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .16em;
  color: var(--fg-mute);
}
html[data-site-theme="rift"] .foot .foot-links a {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-3);
}
html[data-site-theme="rift"] .foot .foot-links a:hover {
  color: var(--rf-ember-hot);
}
html[data-site-theme="rift"] .foot .foot-legal {
  border-top: 1px solid var(--rf-hair);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  color: var(--fg-mute);
}


/* -------------------------------------------------------------------------
   12b. THE LIVE BAR — the fault's readout, pinned to the floor
   ---------------------------------------------------------------------------
   site.js builds it on every page, so a theme that leaves it alone ships a
   strip of the house look across the bottom of a page that is otherwise not
   the house look. It gets the same material as everything else: a top ember
   hairline, mono caps at label size, and the state lamp kept exactly as
   site.js publishes it (ok/warn/bad on .lb-src) rather than re-invented.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"] #wc-livebar {
  box-shadow: none;
  border-radius: 0;
  background-color: var(--rf-slab-lit);
  background-image: linear-gradient(180deg,
    var(--rf-ember-ghost) 0, transparent 60%);
  backdrop-filter: blur(16px) saturate(1.15);
  -webkit-backdrop-filter: blur(16px) saturate(1.15);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
}
html[data-site-theme="rift"] #wc-livebar::before {
  background-image: linear-gradient(90deg,
    var(--rf-ember) 0,
    var(--rf-ember-hair) 34%,
    transparent 72%);
}
html[data-site-theme="rift"] #wc-livebar .lb-src {
  border-radius: 0;
  font-family: var(--font-mono);
  letter-spacing: .16em;
}


/* -------------------------------------------------------------------------
   13. MOTION — the ember travels, and it is never load-bearing
   ---------------------------------------------------------------------------
   Two animations, both on the fault, both transform/opacity only. The page is
   COMPLETE without either: they add heat to a line that is already drawn.
   Gated on the house motion switch AND on the reader's own preference, in
   that order, because a reader who asked for stillness outranks a manifest.
   ------------------------------------------------------------------------- */
html[data-site-theme="rift"][data-wc-motion="on"] .section.wrap::before {
  animation: rf-travel 9s ease-in-out infinite;
}
html[data-site-theme="rift"][data-wc-motion="on"] .section .sec-head::before {
  animation: rf-lamp 4.4s ease-in-out infinite;
}
@keyframes rf-travel {
  0%   { opacity: calc(.30 + .58 * var(--rf-lit)); }
  50%  { opacity: calc(.42 + .74 * var(--rf-lit)); }
  100% { opacity: calc(.30 + .58 * var(--rf-lit)); }
}
@keyframes rf-lamp {
  0%   { transform: scaleX(1); }
  50%  { transform: scaleX(1.5); }
  100% { transform: scaleX(1); }
}
html[data-site-theme="rift"] .section .sec-head::before {
  transform-origin: left center;
}
@media (prefers-reduced-motion: reduce) {
  html[data-site-theme="rift"][data-wc-motion="on"] .section.wrap::before,
  html[data-site-theme="rift"][data-wc-motion="on"] .section .sec-head::before {
    animation: none;
  }
}


/* -------------------------------------------------------------------------
   14. WIDTH — the fault narrows, it never disappears
   ---------------------------------------------------------------------------
   The track is a clamp so it shrinks continuously rather than snapping, and
   these are the two places where a continuous shrink is not enough: the live
   board stops being three cells across at tablet, and the hero band shortens
   on a phone so the copy is not pushed off the first screen.

   ★ THE NAV ROW WRAPS, IT DOES NOT SCROLL. A clipped scroll container hides
   navigation and fails upward - the widest monitor shows the least (memory
   law, Frontier Prime 2026-08-13). The house look already wraps; this only
   makes sure nothing here re-introduces a fixed row.
   ------------------------------------------------------------------------- */
/* ★ THE `:has()` ON `.status-figs` OUT-SPECIFIES A PLAIN DESCENDANT CHAIN.
   site.css collapses the board to two columns with
   `.status-figs:has(.fig:nth-child(2):last-child)`, and a `:has()` takes the
   specificity of its most specific argument - (0,3,0) here - so that rule
   scores (0,4,0) and beats `html[data-site-theme="rift"] .status .status-figs`
   at (0,3,2) outright, being last in the file notwithstanding. An owner with
   no map page has exactly two figures, so it matched, and the phone kept two
   175px cells that overflowed their card. Every rule that moves this grid
   therefore carries the same `:has()`. */
@media (max-width: 1080px) {
  html[data-site-theme="rift"] .status .status-figs,
  html[data-site-theme="rift"] .status .status-figs:has(.fig:nth-child(2):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  html[data-site-theme="rift"] .status .fig:nth-child(3) {
    border-inline-start: 0;
    border-top: 1px solid var(--rf-hair);
    grid-column: 1 / -1;
  }
}
/* ★★★★★ THE NAME COMES BACK BESIDE THE MARK ON EVERY WIDTH.
   cinema.css screen-reader-hides `.brand-txt` below 1064px - `position:
   absolute; width: 1px; clip: rect(0,0,0,0)` - so on a tablet and on every
   phone the top left of the site is a bare picture with no name on it. That
   is a reasonable default for a house look competing with twelve nav links,
   and it is the exact opposite of this owner's instruction ("for the logo put
   it next to the name on the top left"), which does not have a width on it.

   So it is restored, and PAID FOR rather than just switched back on: the mark
   steps down, the name steps down with it, and the TAGLINE goes instead -
   which is the same trade site.css already makes at 460px and the honest one,
   because the name is the identity and the tagline is decoration it repeats.
   Measured at 390px: mark 36 + rule 22 + name 118 = 176px of a 354px row,
   with the burger, the sound control and the sign-in gate taking 152px. */
@media (max-width: 1064px) {
  html[data-site-theme="rift"] .nav .brand .brand-txt {
    position: static;
    width: auto;
    height: auto;
    padding: 0 0 0 12px;
    margin: 0 0 0 12px;
    overflow: visible;
    clip: auto;
    clip-path: none;
    white-space: normal;
  }
  html[data-site-theme="rift"] .nav .brand .brand-txt b {
    font-size: 17px;
  }
}
@media (max-width: 820px) {
  html[data-site-theme="rift"] {
    --rf-track: 22px;
    --rf-cut: 18px;
    --rf-cut-y: 9px;
  }
  html[data-site-theme="rift"] .nav .brand .brand-txt > span {
    display: none;
  }
  html[data-site-theme="rift"] .nav .brand .brand-txt b {
    font-size: 15.5px;
  }
  html[data-site-theme="rift"] .nav .nav-in {
    min-height: 62px;
    gap: 10px;
  }
  html[data-site-theme="rift"] .hero .hero-grid {
    min-height: clamp(460px, calc(100svh - 62px), 760px);
  }
  html[data-site-theme="rift"] .hero .hero-copy {
    max-width: none;
  }
  html[data-site-theme="rift"] .nav .brand img {
    width: 42px;
    height: 42px;
  }
  html[data-site-theme="rift"] .nav .brand .brand-txt {
    padding-inline-start: 11px;
    margin-inline-start: 11px;
  }
  html[data-site-theme="rift"] .nav .brand .brand-txt b {
    font-size: 17px;
  }
  html[data-site-theme="rift"] .status .status-figs,
  html[data-site-theme="rift"] .status .status-figs:has(.fig:nth-child(2):last-child) {
    grid-template-columns: minmax(0, 1fr);
  }
  html[data-site-theme="rift"] .status .fig + .fig {
    border-inline-start: 0;
    border-top: 1px solid var(--rf-hair);
  }
  html[data-site-theme="rift"] .status .fig:nth-child(3) {
    grid-column: auto;
  }
  /* one across, because three 115px cells is not three cards, it is a row of
     slivers - and the house look already made this call at this width; the
     only reason it needs restating is that section 10 raised the desktop rule
     above it. */
  html[data-site-theme="rift"] .grid.grid-3,
  html[data-site-theme="rift"] .grid.grid-2,
  html[data-site-theme="rift"] .grid.grid-4 {
    grid-template-columns: minmax(0, 1fr);
  }
  html[data-site-theme="rift"] .sec-head h2 {
    max-width: none;
  }
}
@media (min-width: 821px) and (max-width: 1100px) {
  html[data-site-theme="rift"] .grid.grid-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ★ FORCED COLOURS. Every shape in this theme is drawn with a background or a
   clip, both of which a forced-colours mode discards - so the frame comes
   back as a real border and the clips are dropped, because a clipped element
   with no fill is an invisible one. */
@media (forced-colors: active) {
  html[data-site-theme="rift"] .card,
  html[data-site-theme="rift"] .feat,
  html[data-site-theme="rift"] .status,
  html[data-site-theme="rift"] .btn,
  html[data-site-theme="rift"] .feat .feat-ico,
  html[data-site-theme="rift"] .steps li::before {
    clip-path: none;
    border: 1px solid CanvasText;
  }
  html[data-site-theme="rift"] .card::before,
  html[data-site-theme="rift"] .feat::before,
  html[data-site-theme="rift"] .status::before {
    display: none;
  }
}
/* SITEFIX 2026-10-16: the fold hairline (.hero::after) reaches past the right edge by the gutter - clip main at the viewport */
html[data-site-theme="rift"] main{overflow-x:clip}
