/* ============================================================================
   RING SCENE FRAMEWORK — the shared skin for scenes 3-7.
   ----------------------------------------------------------------------------
   Scenes 3-7 all use the identical six-beat grammar (BUILD-SPEC §4). Bespoke
   styling per scene produces five different videos instead of one, so every
   rule in this file is deliberately scene-agnostic: an individual scene file
   supplies a mechanic and nothing else.

   Hard constraints encoded here (BUILD-SPEC §2, §5):
     - No @keyframes and no transitions on anything animated. Every visual
       state is a pure function of the scene timeline's position; CSS declares
       resting states only.
     - Nothing that reads as a ring, lane or connection renders solid: dash
       patterns are permanent and are revealed through an SVG <mask>, never
       through stroke-dasharray. Nothing here is delivered.
     - Nothing draws along the bottom edge of the frame (C3.2). The horizontal
       journey strip that used to live at y 826-896 is deleted; the phase
       indicator is the vertical left rail in video.css.
     - Status colour paints swatches, strokes and fills. Never text colour.
       This file sets `color` from a token only — never from --status-*.
     - Nothing below 14px at the 1600x900 authoring size. Measured, not
       assumed: see the audit in ring-scene.js.
   ========================================================================= */

/* ---- the 1600x900 authoring canvas ---------------------------------------
   Same pure-CSS fit as .sh (see shield.css for why there is no listener and
   no ResizeObserver in the path). Clamped at 1 so text is never
   transform-upscaled; capture at 1600x900 lands on exactly 1. */
.rs {
  position: absolute;
  left: 50%; top: 50%;
  width: 1600px; height: 900px;
  --rs-k: min(1, calc(100vw / 1600px), calc(100vh / 900px));
  transform: translate(-50%, -50%) scale(var(--rs-k));
  transform-origin: 50% 50%;
  font-family: var(--font-body);
  color: var(--fg-primary);
  /* Iframes would otherwise swallow the wheel events that drive the clock.
     pointer-events inherits, so this one declaration covers every mockup. */
  pointer-events: none;
}

/* ---- status -> --sc cascade ----------------------------------------------
   Identical single hop to shield.css. Nothing downstream may set `color` from
   it, which makes the "status colour as text colour" contrast failure
   structurally impossible rather than a review item. */
.rs [data-status="progress"] { --sc: var(--status-progress); }
.rs [data-status="testing"]  { --sc: var(--status-testing);  }
.rs [data-status="blocked"]  { --sc: var(--status-blocked);  }
.rs [data-status="paused"]   { --sc: var(--status-paused);   }
.rs [data-status="pipeline"] { --sc: var(--status-pipeline); }

/* ---- the anchor plane -----------------------------------------------------
   The framework's slot for scene-owned stage geometry — scene 3's lane is the
   only tenant today. The bottom journey strip that used to live here is
   deleted (C3.2) and the concentric arcs went with the shield before it;
   both sets of classes are gone from this file, not merely unused.

   overflow is left at the SVG default (hidden) on purpose: geometry is drawn
   in a 1600x900 viewBox and a scene may deliberately run a stroke off the
   edge. .stage only clips at the viewport, so at --rs-k < 1 an overflowing
   stroke would paint over the shell's chrome. */
.rs__anchorwrap {
  position: absolute; inset: 0;
  perspective: 1600px;
  perspective-origin: 20% 70%;
}
.rs__anchor { position: absolute; inset: 0; }
.rs__anchor > svg { position: absolute; inset: 0; width: 100%; height: 100%;
                    shape-rendering: geometricPrecision; }

/* ---- DELETED: the bottom journey strip and its interception (C3.2) --------
   .rs-arm__dot (the sweep dot travelling the journey line) and every .rs-int__*
   rule (the traveller, its halo and the fork pulse) are gone, along with the
   geometry in ring-scene.js that used them. The author's instruction is that a
   phase indicator never sits at the bottom of the frame, "not even towards the
   end". Wayfinding is the vertical LEFT rail in video.css (.phaserail).

   Do not re-add a class here that paints below y=800. */

/* ---- the title stack (beat 2) -------------------------------------------- */
/* Knocked out of the anchor arcs with the surface colour, the same way every
   string on the shield is. */
.rs__head {
  position: absolute; left: 96px; top: 176px; width: 412px;
}
.rs__mark {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-display-lg);
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--fg-primary);
  font-variant-numeric: tabular-nums;
  clip-path: inset(0% 0% 0% 0%);
}
.rs__name {
  display: block;
  margin-top: var(--space-3);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-display-md);
  line-height: var(--lh-display-md);
  letter-spacing: -.02em;
  color: var(--fg-primary);
  clip-path: inset(0% 0% 0% 0%);
}
.rs__rule {
  margin: var(--space-5) 0;
  width: 412px; height: 1px;
  background: var(--border-default);
  transform-origin: 0% 50%;
}
.rs__promise {
  display: block;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--text-xl);
  line-height: var(--lh-xl);
  color: var(--fg-tertiary);
  clip-path: inset(0% 0% 0% 0%);
}

/* ---- the client-feel beat-out (beat 5) -----------------------------------
   Max 12 words (BUILD-SPEC §7) — enforced in ring-scene.js, not here.
   Marked by a short rule ABOVE the quote, echoing the head block's rule so
   the two text blocks rhyme. Deliberately not a coloured left border: a bar
   down the side of a copy block reads as a status swatch, and status colour
   has exactly one job in this video. */
.rs__feel {
  position: absolute; left: 96px; top: 588px; width: 430px;
  padding: var(--space-3) var(--space-4) var(--space-2) 0;
  background: var(--bg-primary);
  clip-path: inset(0% 0% 0% 0%);
}
.rs__feel::before {
  content: '';
  display: block;
  width: 56px; height: 2px;
  margin-bottom: var(--space-3);
  background: var(--fg-primary);
}
.rs__feel q {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-display-xs);
  line-height: var(--lh-display-xs);
  letter-spacing: -.01em;
  color: var(--fg-primary);
  quotes: '\201C' '\201D';
}

/* ---- the honest-state ledger (left column, beat 4) -----------------------
   The band the framework leaves between the promise line (ends at y=351) and
   the client-feel quote (plate starts at y=588) is where a ring scene states
   what it is actually looking at: the project, its status, and what is
   holding it up. This is grammar, not decoration — the viewer learns within
   two scenes to look bottom-left for the honest state, and two of the five
   scenes used to have nothing there while the frame showed Salesforce and SAP
   apparently working. Over 60s of a 237s film, the only thing saying "not
   delivered" was the header chip.

   Built by ctx.ledger() in ring-scene.js so all five scenes share one
   implementation and one look, rather than each growing its own.

   Every row is knocked out of the anchor arcs with the surface colour, the
   same way .rs__feel and every string on the shield is: the scene's own
   dashed ring is a full-opacity stroke that sweeps straight through this band
   and would otherwise strike through the project names. width:max-content
   keeps the knockout tight to the text instead of painting a 436px white slab
   across the arc, and the clip-path is what ctx.wipe drives, so the plate is
   never revealed ahead of the words it carries. */
.rs__ledger { position: absolute; left: 96px; width: 436px; }

/* The headline: one project, uppercase, with its status swatch. */
.rs__lstat {
  display: flex; align-items: center; gap: 10px;
  height: 22px;
  clip-path: inset(0% 0% 0% 0%);
}
/* §5: status colour paints the swatch. It is never a letterform. */
.rs__lsw {
  width: 11px; height: 11px;
  border-radius: var(--radius-full);
  background: var(--sc);
  flex: none;
}
.rs__lname {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  line-height: var(--lh-sm);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  white-space: nowrap;
  background: var(--bg-primary);
  padding: 0 6px; margin-left: -6px;
}
/* The owner / known-issue line that hangs under the headline. */
.rs__lnote {
  width: max-content; max-width: 436px;
  margin-top: var(--space-1);
  padding: 0 var(--space-3) 0 21px;
  background: var(--bg-primary);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--text-sm);
  line-height: var(--lh-sm);
  color: var(--fg-tertiary);
  clip-path: inset(0% 0% 0% 0%);
}

/* A capability row under the headline — the scene's own CONTENT points. */
.rs__lpt {
  position: relative;
  width: max-content; max-width: 436px;
  height: 28px;
  padding: 0 var(--space-3) 0 21px;
  display: flex; align-items: center;
  background: var(--bg-primary);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-md);
  line-height: var(--lh-md);
  color: var(--fg-secondary);
  clip-path: inset(0% 0% 0% 0%);
}
.rs__lpt::before {
  content: ''; position: absolute; left: 3px; top: 13px;
  width: 5px; height: 5px;
  border-radius: var(--radius-full);
  background: var(--border-strong);
}

/* A project row — name, status, and the blocker/owner that follows it. Used
   where a scene owns more than one project and none of them is the headline. */
.rs__lrow {
  position: relative;
  width: max-content; max-width: 436px;
  margin-top: var(--space-1);
  padding: 0 var(--space-3) 0 21px;
  background: var(--bg-primary);
  clip-path: inset(0% 0% 0% 0%);
}
.rs__lrow:first-child { margin-top: 0; }
.rs__lrow::before {
  content: ''; position: absolute; left: 0; top: 6px;
  width: 8px; height: 8px;
  border-radius: var(--radius-full);
  background: var(--sc);
}
.rs__lrow b, .rs__lrow span, .rs__lrow em {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  line-height: var(--lh-sm);
  font-style: normal;
}
.rs__lrow b { font-weight: 600; color: var(--fg-primary); }
.rs__lrow span { font-weight: 400; color: var(--fg-muted); }
.rs__lrow em { font-weight: 400; color: var(--fg-tertiary); }

/* ---- the screen frame (beats 3, 4, 6) ------------------------------------
   A viewport onto a vendor system, not a screenshot pasted on the stage. The
   frame clips; the mockup inside it is panned and pushed into by the mechanic.
   1000x680 at (540,116) keeps clear of the shell's rail on the right and its
   transport at the bottom.

   RECORDED EXEMPTION from the kit's border-OR-shadow card rule: the bezel is
   a viewport onto a vendor system, not a card. The 1px border is the
   viewport's clipping edge (without it a white mockup region bleeds into the
   white canvas) and the shadow is the lift that separates the vendor plane
   from the Equiti stage. Both are load-bearing; do not re-flag. */
.rs__frame {
  position: absolute; left: 540px; top: 116px; width: 1000px; height: 680px;
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-secondary);
  box-shadow: var(--shadow-xl);
}
/* ---- mac browser chrome (C3.4) -------------------------------------------
   The frame is 1000x680; the fitted mockup is 1000x625. 27.5px of empty
   --bg-secondary already sat above and below every screen, and the author
   wants that top gap to read as a browser window rather than as padding.

   27.5px IS NOT A ROUND NUMBER BY ACCIDENT. It is exactly (680 - 750 x 5/6)/2,
   the gap the establishing fit already leaves, so this bar covers what was
   there and nothing else: frame size, mockup scale and every pushTo() are
   untouched. If .rs__frame or the 1200x750 mockup canvas ever changes, this
   height has to be recomputed or the bar will crop a live mockup.

   It sits ABOVE the screens (z-index) and does not move when a mechanic pushes
   in — window chrome does not scroll with the page, and that is what makes the
   push read as a zoom into a browser rather than a zoom of a picture.

   The three hexes are macOS system colours, quoted exactly by C3.4. They are a
   depiction of an OS control, not a palette choice — the same exemption the
   vendor mockups run on. Nothing else in this file may hard-code a colour. */
.rs__chrome {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 27.5px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 14px;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-subtle);
}
.rs__light {
  flex: none;
  width: 11px; height: 11px;
  border-radius: var(--radius-full);
}
.rs__light--r { background: #FF5F57; }
.rs__light--a { background: #FEBC2E; }
.rs__light--g { background: #28C840; }

/* One wrapper per mounted mockup, all stacked on the frame's origin. The
   transform (x / y / scale) is what the camera helpers drive. */
.rs__screen {
  position: absolute; left: 0; top: 0;
  width: 1200px; height: 750px;
  transform-origin: 0% 0%;
}
.rs__screen > iframe {
  display: block;
  width: 1200px; height: 750px;
  border: 0;
  background: var(--equiti-white);
}
/* Shown only when a mockup failed to preload, so the failure is visible on
   the stage instead of silently composing an empty frame. */
.rs__missing {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: var(--space-8);
  background: var(--bg-tertiary);
  color: var(--fg-muted);
  font-size: var(--text-md);
  line-height: var(--lh-md);
  text-align: center;
}

/* ---- vendor attribution --------------------------------------------------
   BUILD-SPEC §6b: naming beats depicting. Every vendor identification in this
   video is a word mark in plain text, which is both what the licences permit
   and what the real products display. 14px — the §5 floor, no exemption for
   chrome. */
.rs__lab { position: absolute; left: 540px; top: 80px; width: 1000px; height: 22px; }
.rs__lab > span {
  position: absolute; left: 0; top: 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  line-height: var(--lh-sm);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-muted);
  white-space: nowrap;
}

/* ---- reduced motion ------------------------------------------------------
   Nothing to disable: this file declares no transition and no keyframe. The
   held frame is complete because the timeline's last motion lands at 0.90,
   which is where clock.js snaps (boot.js registers each scene's mark there). */
