/* JARVIS — built FROM the approved sample, not from a memory of it.
 *
 * Three times I built something "inspired by" the mockup and three times it
 * was a different thing. His words: "what you have built is something totally
 * different, not the one that you gave as sample."
 *
 * So this file starts from that file. The palette, the ground, the ambient
 * layers, the corner-cut frames, the button shapes and the HUD composition are
 * lifted from it directly. What is added is the mapping: the platform's own
 * vocabulary — .panel, .btn, .field, .label — painted to match, so 84 screens
 * that never heard of a HUD still wear the look.
 *
 * Two layers live here:
 *   the VOCABULARY, which every screen uses;
 *   the HUD (.jv …), which the film page uses, namespaced so it collides with
 *     nothing and costs nothing on the pages that do not render it.
 */

:root {
  /* the approved palette, verbatim */
  --n0:#03252c; --deep:#08343c; --teal:#0b3d45;
  --i1:#0d5f6b; --i2:#00a9c4; --i3:#00d8f0; --i4:#5ff4ff; --i5:#e8ffff;
  --o1:#5a2a05; --o2:#c96a12; --o3:#ff8a1f; --o4:#ffb964; --o5:#ffe3c4;
  --v1:#2a1050; --v2:#6b2fc0; --v3:#a869ff; --v4:#d2a6ff;
  --g3:#00e676; --g4:#7dffb4;
  --r3:#ff4f6d; --r4:#ff97a8;
  --hot:#ffffff;

  /* what the contract requires, pointed at the above */
  --bg: var(--n0);
  --text: #dcfbff;
  --muted: #7fb0bd;
  --line: color-mix(in srgb, var(--i2) 34%, transparent);
  --surface: #072e37;
  --on-accent: #02171c;
  --accent: var(--i3);
  --needs-you: var(--o3);
  --failed: var(--r3);
  --done: var(--g3);
  --working: var(--i4);
  /* §1 of the spec gives every colour a role, and two of them are asked for
     by the ring: "violet is depth", and --hot is the white core of a lit arc.
     They are tokens rather than hex in the component so a third theme with a
     warm palette gets its own depth instead of this one's purple. */
  --depth: var(--v3);
  --failed-edge: color-mix(in srgb, var(--r3) 45%, transparent);
  --warning-edge: color-mix(in srgb, var(--o3) 45%, transparent);
  --font-body: "Rajdhani", ui-sans-serif, system-ui, sans-serif;
  --font-display: "Rajdhani", ui-sans-serif, system-ui, sans-serif;
  --font-stat: "ShareTechMono", ui-monospace, monospace;

  --pad: 1.05rem; --pad-tight: .8rem;
  --cut: 14px;
  color-scheme: dark;
}

/* ── THE GROUND, from the sample ─────────────────────────────────────── */
/* THE GROUND IS ON html, NOT IN THE STACK.
   In the sample the ground gradient is body's ONLY background image, so it
   fills the page. Stacking it twelfth behind the bokeh, under `no-repeat`
   with `background-size: auto`, made it a 1400x820 patch pinned to the top
   left — everything outside that box fell back to flat --n0, which is why
   the background came out nothing like the sample. It gets its own element
   so no later layer can resize or reposition it. */
html {
  background:
    radial-gradient(1400px 820px at 50% 46%, var(--teal) 0%, var(--deep) 42%, var(--n0) 76%),
    var(--n0);
  background-attachment: fixed;
  background-repeat: no-repeat;
  background-size: cover;
  min-height: 100%;
}
body {
  margin: 0; color: var(--text); font-family: var(--font-body); font-size: 15px;
  background:
    radial-gradient(1400px 820px at 50% 40%, var(--teal) 0%, var(--deep) 42%, var(--n0) 76%);
  background-color: var(--n0);
  background-attachment: fixed;
}
/* ── §2 OF THE SPEC: SEVEN AMBIENT LAYERS ─────────────────────────────
   The built theme had two of these and that is most of why it read flat
   against the sample. Placed without adding a single element: the bokeh and
   the streak ride on body's own background, the grid and the spokes on its
   two pseudo-elements, the vignette as an inset shadow, and the two lens
   flares on html's. Seven layers, no wrapper. */

/* 1 · bokeh — ten soft points, warm and cool   2 · streak — the light line */
body {
  background-image:
    radial-gradient(3px 3px at 12% 22%, color-mix(in srgb,var(--o4) 60%,transparent), transparent),
    radial-gradient(2px 2px at 26% 78%, color-mix(in srgb,var(--o3) 50%,transparent), transparent),
    radial-gradient(4px 4px at 88% 34%, color-mix(in srgb,var(--o4) 45%,transparent), transparent),
    radial-gradient(2px 2px at 71% 88%, color-mix(in srgb,var(--o5) 50%,transparent), transparent),
    radial-gradient(3px 3px at 47% 12%, color-mix(in srgb,var(--i4) 45%,transparent), transparent),
    radial-gradient(2px 2px at 8%  61%, color-mix(in srgb,var(--i4) 40%,transparent), transparent),
    radial-gradient(5px 5px at 93% 72%, color-mix(in srgb,var(--o3) 36%,transparent), transparent),
    radial-gradient(2px 2px at 58% 94%, color-mix(in srgb,var(--i4) 50%,transparent), transparent),
    radial-gradient(3px 3px at 34% 44%, color-mix(in srgb,var(--i5) 35%,transparent), transparent),
    radial-gradient(2px 2px at 79% 9%,  color-mix(in srgb,var(--o4) 55%,transparent), transparent),
    linear-gradient(90deg, transparent,
      color-mix(in srgb,var(--i4) 30%,transparent) 30%,
      color-mix(in srgb,var(--i5) 55%,transparent) 50%,
      color-mix(in srgb,var(--i4) 30%,transparent) 70%, transparent);
  background-color: transparent;
  background-repeat: no-repeat;
  background-size: auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, 100% 1px;
  background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 46vh;
  background-attachment: fixed;
}

/* 3 · the 54px grid, masked to an oval   7 · the vignette */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: .45;
  background:
    linear-gradient(color-mix(in srgb, var(--i2) 10%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--i2) 10%, transparent) 1px, transparent 1px);
  background-size: 54px 54px;
  -webkit-mask: radial-gradient(70% 58% at 50% 46%, #000, transparent 92%);
          mask: radial-gradient(70% 58% at 50% 46%, #000, transparent 92%);
  box-shadow: inset 0 0 260px 70px var(--n0);
}

/* 4 · the spokes, 1.7deg on 1.85deg, turning once every five minutes */
body::after {
  content: ""; position: fixed; left: 50%; top: 46%; width: 1800px; height: 1800px;
  translate: -50% -50%; pointer-events: none; z-index: 0;
  background: repeating-conic-gradient(from 0deg,
    transparent 0 1.7deg, color-mix(in srgb, var(--i2) 14%, transparent) 1.7deg 1.85deg);
  -webkit-mask: radial-gradient(transparent 22%, #000 32%, transparent 58%);
          mask: radial-gradient(transparent 22%, #000 32%, transparent 58%);
  animation: jv-rot 300s linear infinite;
}
@keyframes jv-rot { to { rotate: 360deg } }

/* 5 · 6 · the two lens flares — a white pip, a halo, a cross streak */
html::before, html::after {
  content: ""; position: fixed; width: 4px; height: 4px; border-radius: 50%;
  background: var(--hot); pointer-events: none; z-index: 0;
}
html::before {
  left: 23%; top: 34%;
  box-shadow:
    0 0 10px 3px color-mix(in srgb,var(--i4) 60%,transparent),
    0 0 28px 9px color-mix(in srgb,var(--i3) 26%,transparent);
  animation: jv-tw 5s ease-in-out infinite;
}
html::after {
  left: 77%; top: 63%;
  box-shadow:
    0 0 14px 5px color-mix(in srgb,var(--o4) 70%,transparent),
    0 0 40px 14px color-mix(in srgb,var(--o3) 30%,transparent);
  animation: jv-tw 7s ease-in-out infinite .8s;
}
@keyframes jv-tw { 50% { opacity: .45; scale: .8 } }
main, header, nav, .sidebar { position: relative; z-index: 1; }

/* ── PANEL = the sample's corner-cut frame ───────────────────────────── */
.panel {
  position: relative; padding: var(--pad);
  background: linear-gradient(color-mix(in srgb, #0a1c3c 66%, transparent),
                              color-mix(in srgb, var(--n0) 78%, transparent));
  border: 1px solid var(--line);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)),
                     calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
}
.panel::before { content:""; position:absolute; left:0; top:0; width:16px; height:2px;
  background: var(--i3); box-shadow: 0 0 12px -1px var(--i3); }
.panel::after  { content:""; position:absolute; right:0; bottom:0; width:16px; height:2px;
  background: var(--o3); box-shadow: 0 0 12px -1px var(--o3); }
.panel.tight { padding: var(--pad-tight); }
.panel.flush { padding: 0; }

.card {
  position: relative; padding: var(--pad-tight);
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  border: 1px solid var(--line);
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
}
.card::before { content:""; position:absolute; left:0; top:0; width:12px; height:1px; background: var(--i3); }

/* ── TYPE ────────────────────────────────────────────────────────────── */
h1,h2,h3 { font-family: var(--font-display); color: var(--text); }
h1 { font-weight:700; font-size:1.7rem; letter-spacing:.14em; text-transform:uppercase; }
h1::after {
  content:""; display:block; height:7px; margin-top:.4rem;
  background: repeating-linear-gradient(90deg, color-mix(in srgb,var(--i3) 55%,transparent) 0 1px, transparent 1px 9px);
  -webkit-mask: linear-gradient(90deg,#000,transparent 55%); mask: linear-gradient(90deg,#000,transparent 55%);
}
h2 { font-weight:600; letter-spacing:.06em; }
/* See cockpit.css: a heading that reuses `.label` looks exactly like the rows
   it is meant to head, which is no heading at all. */
.bucket {
  display:block; margin-top:.25rem; padding-top:1rem;
  border-top:1px solid var(--line);
  font-family: var(--font-stat); font-size:11px; letter-spacing:.18em;
  text-transform:uppercase; color: var(--i4); margin-bottom:.35rem;
}

.label {
  display:block; font-family: var(--font-stat); font-size:8.5px; letter-spacing:.3em;
  text-transform:uppercase; color: var(--muted); margin-bottom:.35rem;
}
/* .3em is right over a form field and far too wide for a sentence: "BLOCKED
   ON YOU, AND ONLY ON YOU" spread across two lines and read as shouting --
   "that top line is exaggerated". Inside an instrument it tightens. */
.jv .wing .label{letter-spacing:.14em;font-size:9px;margin-bottom:.5rem;
  color:color-mix(in srgb,var(--muted) 60%,var(--text))}
.muted { color: var(--muted); }
.stat { font-family: var(--font-stat); font-variant-numeric: tabular-nums; }
.stat-big { font-family: var(--font-display); font-weight:700; color: var(--i4);
  text-shadow: 0 0 20px color-mix(in srgb, var(--i3) 50%, transparent); }

/* ── FIELDS ──────────────────────────────────────────────────────────── */
.field {
  width:100%; padding:.52rem .7rem; border-radius:0;
  background: color-mix(in srgb, var(--n0) 86%, #000);
  color: var(--text); border:1px solid var(--line);
  border-left:2px solid color-mix(in srgb, var(--i2) 60%, transparent);
  font-family: var(--font-body); font-size:15px;
}
.field::placeholder { color: color-mix(in srgb, var(--muted) 68%, transparent); }
.field:focus { outline:none; border-color: color-mix(in srgb,var(--i3) 62%,transparent);
  border-left-color: var(--i4); }
select.field { appearance:none; padding-right:1.9rem;
  background-image:linear-gradient(45deg,transparent 50%,var(--i3) 50%),
                   linear-gradient(135deg,var(--i3) 50%,transparent 50%);
  background-position:calc(100% - 15px) 52%,calc(100% - 10px) 52%;
  background-size:5px 5px,5px 5px; background-repeat:no-repeat; }

/* ── BUTTONS = the sample's clipped, glowing press ───────────────────────
   EVERY MODIFIER STANDS ALONE. 33 places in the platform write `btn-ghost`
   with no `btn` beside it, and the first version of this theme put the shape
   and the padding only on `.btn` -- so "+ New channel" on Home rendered as
   bare text. A modifier that needs a partner is a modifier that will be used
   without one. */
.btn, .btn-primary, .btn-ghost, .btn-danger {
  display:inline-flex; align-items:center; justify-content:center;
  font-family: var(--font-display); font-weight:700; font-size:12px;
  letter-spacing:.2em; text-transform:uppercase;
  padding:.6rem 1.4rem; border:1px solid transparent; border-radius:0; cursor:pointer;
  clip-path: polygon(10px 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
  text-decoration:none;
}
.btn-primary {
  background: linear-gradient(90deg, var(--i3), var(--i4));
  color: var(--on-accent); box-shadow: 0 0 34px -8px var(--i4);
}
.btn-primary:hover { background: linear-gradient(90deg, var(--i4), var(--i5)); }
.btn-ghost { background:transparent; color: var(--muted); border-color: var(--line); }
.btn-ghost:hover { color: var(--i4); border-color: var(--i3); }
.btn-danger { background:transparent; color: var(--r3); border-color: var(--failed-edge); }
.btn-danger:hover { background: color-mix(in srgb, var(--r3) 14%, transparent); }
.btn-compact { padding:.32rem .8rem; font-size:10px; letter-spacing:.14em; }
.btn:disabled, .btn-primary:disabled, .btn-ghost:disabled { opacity:.45; cursor:not-allowed; }

/* ── BADGES, SHELL, EMPTY ────────────────────────────────────────────── */
.badge { display:inline-block; font-family:var(--font-stat); font-size:9px;
  letter-spacing:.18em; text-transform:uppercase; padding:.18rem .5rem;
  border:1px solid var(--line); color: var(--muted); }
.badge-alert { color: var(--o3); border-color: var(--warning-edge);
  background: color-mix(in srgb, var(--o3) 12%, transparent); }

/* ── R4 · NAVIGATION IS THE ONE ALREADY THERE, RESTYLED ───────────────
   "no this is wrong.. there is already navigation currently on top coming
   from existing layout.. u change the UI of that to reflect the new design..
   and dont put the navigation at bottom."

   So nothing moves and nothing is added. The sidebar that has always been
   there becomes an instrument panel: a notched corner where it meets the
   work, a lit rail down the item you are standing on, and a pip on its right
   edge -- the mark the approved file puts on a live channel. */
.sidebar { background: linear-gradient(180deg, var(--deep), color-mix(in srgb,var(--n0) 92%,#000));
  border-right:1px solid var(--line); border-bottom:1px solid var(--line);
  /* The one corner that faces the work is cut, like every other panel. */
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 22px), calc(100% - 22px) 100%, 0 100%); }
/* On a phone the sidebar is a bar across the top, so the notch belongs on the
   bottom-right of the bar rather than of a column. */
@media (max-width:1023px){ .sidebar{ clip-path:none; } }

/* ── THE SIDEBAR'S OWN INSTRUMENT EDGE ────────────────────────────────
   "the side bar looks blank and empty.. but some design across the vertical
   side bar." It was a brand, six links and a footer with a long dead gap in
   the middle of it.

   What fills the gap is geometry, not words and not links: a lit rail down the
   edge that faces the work, a fixed-pitch tick scale beside it in the wings'
   own hatch, and a bracket at each end. Nothing here is a control and nothing
   here is information, so nothing is said twice and there is nothing new to
   learn -- it reads as the side of an instrument, which is what it is.

   Desktop only. On a phone the same class is a bar across the top, where a
   vertical rail would be nonsense. */
@media (min-width:1024px) {
  .sidebar { position: relative; }
  /* The rail and its scale, down the inner edge, fading out at both ends so it
     never looks like a border that stopped. */
  .sidebar::before {
    content: ""; position: absolute; right: 0; top: 76px; bottom: 76px; width: 16px;
    pointer-events: none; z-index: 0;
    background:
      linear-gradient(to bottom, transparent,
        color-mix(in srgb, var(--i3) 55%, transparent) 14%,
        color-mix(in srgb, var(--i3) 55%, transparent) 86%, transparent)
        right top / 1px 100% no-repeat,
      repeating-linear-gradient(to bottom,
        color-mix(in srgb, var(--i2) 45%, transparent) 0 1px, transparent 1px 13px)
        right 4px top / 9px 100% no-repeat;
  }
  /* A bracket at each end of the rail, drawn as four gradients on one
     pseudo-element so no element is added to the shell. */
  .sidebar::after {
    content: ""; position: absolute; right: 5px; top: 58px; bottom: 58px; width: 18px;
    pointer-events: none; z-index: 0;
    background-image:
      linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4)),
      linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4));
    background-repeat: no-repeat;
    background-size: 14px 1px, 1px 12px, 14px 1px, 1px 12px;
    background-position: right top, right top, right bottom, right bottom;
    opacity: .7;
  }
  /* The links sit over it. */
  .sidebar > * { position: relative; z-index: 1; }
}
.navrule { height:1px; margin:.55rem 0;
  background: linear-gradient(90deg, color-mix(in srgb,var(--i3) 45%,transparent), transparent); }
.footer { color: var(--muted); font-family:var(--font-stat); font-size:9px; letter-spacing:.2em; }
.footer-dot { color: var(--i3); }
.nav-link { position:relative; display:block; font-family:var(--font-display); font-size:12px;
  letter-spacing:.2em; text-transform:uppercase; color: var(--muted);
  padding:.42rem .7rem; border-left:2px solid transparent; text-decoration:none; }
.nav-link:hover { color: var(--text); background: color-mix(in srgb,var(--i2) 12%,transparent); }
.nav-link.active { color: var(--i4); border-left-color: var(--i3);
  background: linear-gradient(90deg, color-mix(in srgb,var(--i3) 16%,transparent), transparent); }
/* THE PIP. A lit square on the right edge of where you are -- the one mark
   the sample uses to say "this one is live", and the only thing the sidebar
   was missing against it. */
.nav-link.active::after { content:""; position:absolute; right:9px; top:50%; translate:0 -50%;
  width:4px; height:4px; background: var(--i3); box-shadow: 0 0 7px var(--i3); }
.nav-link.compact { font-size:11px; padding:.28rem .6rem; }
.nav-link.compact.active::after { right:5px; }
.brand { font-family:var(--font-display); font-weight:700; letter-spacing:.34em;
  text-transform:uppercase; color: var(--text); }
.brand-mark { border-radius:50%;
  background: radial-gradient(var(--i5), var(--i3) 45%, var(--i1) 78%);
  box-shadow: 0 0 16px -2px var(--i3); }
.empty { padding:1.5rem; text-align:center; color: var(--muted);
  border:1px dashed color-mix(in srgb,var(--i2) 40%,transparent);
  font-family:var(--font-stat); font-size:11px; letter-spacing:.16em; }

a { color: var(--i4); } a:hover { color: var(--i5); }
/* THE COLUMN IS THE SHELL'S, NOT THE THEME'S.
   This said `max-width: 74ch` — about 700px — which crushed every page,
   the readout worst of all: its composition is a 1320px frame with a wing
   either side of a 520px core, and at 700px beside a sidebar the wings have
   nowhere to go. That one line is why what shipped looked nothing like the
   sample. The shell already sets a readable width; a page that needs the
   whole area asks for it. */
/* ── §3 OF THE SPEC: THE FRAME, ON EVERY PAGE ─────────────────────────
   "everywhre..." — so the notched frame and its four corner brackets wrap
   the content of every screen, not only a film's.

   The column already exists in the shell, so it becomes the frame rather
   than gaining a wrapper: 1px edge, a 22px notch on all four corners, and
   the brackets drawn as eight gradients on one pseudo-element so no element
   is added to any page. */
.content-column {
  position: relative;
  padding: 16px 20px 22px;
  border: 1px solid color-mix(in srgb, var(--i3) 20%, transparent);
  background: linear-gradient(color-mix(in srgb, #03112b 34%, transparent),
                              color-mix(in srgb, var(--n0) 34%, transparent));
  clip-path: polygon(22px 0, calc(100% - 22px) 0, 100% 22px, 100% calc(100% - 22px),
                     calc(100% - 22px) 100%, 22px 100%, 0 calc(100% - 22px), 0 22px);
}
.content-column::before {
  content: ""; position: absolute; inset: 5px; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4)),
    linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4)),
    linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4)),
    linear-gradient(var(--i4), var(--i4)), linear-gradient(var(--i4), var(--i4));
  background-repeat: no-repeat;
  background-size: 20px 1px, 1px 20px, 20px 1px, 1px 20px,
                   20px 1px, 1px 20px, 20px 1px, 1px 20px;
  background-position:
    left top, left top, right top, right top,
    left bottom, left bottom, right bottom, right bottom;
  opacity: .85;
}
.content-column > * { position: relative; z-index: 1; }

/* A page that asks for the whole area still gets it — the readout's
   composition is a 1320px frame and does not fit a reading column. */
.content-column:has([data-fullbleed]) { max-width: none; }
.table-stack { background: var(--surface); }
.grad-gold,.grad-pink,.grad-mint,.grad-sky,.grad-teal,.grad-violet { color: var(--i4); }
::selection { background: color-mix(in srgb,var(--i3) 35%,transparent); color: var(--i5); }
[data-not-applicable] { opacity:.55; }
@media (prefers-reduced-motion: reduce) { *, body::after { animation:none !important }
  html { scroll-behavior:auto } }

/* ══════════════════════════════════════════════════════════════════════
   THE HUD — the sample's composition, lifted.

   Namespaced under .jv so it touches nothing else and costs nothing on the
   83 screens that never render it. Only the film page does, and only where
   the theme asks (`hero: true`).
   ══════════════════════════════════════════════════════════════════════ */
/* ══ THE RING BOX — ONE GEOMETRY, TWO FILES ══════════════════════════════
   R1 of the spec: the ring is the platform's backdrop, not a page's widget.
   src/app/ring.tsx draws the ambient assembly and the ROOT layout mounts it,
   so navigation never unmounts it. A page with film numbers to say draws its
   band, its reading and its seven stages into the SAME box, over the top.

   Both use this class, so the two land on one circle and neither file has to
   know the other's pixels. Change the size here and both follow.

   The centre sits in the middle of the WORK area, not of the window: the
   sidebar is 14rem, so half of it is added back on the wide layout. Without
   that the whole composition reads as pulled to the left. */
:root {
  /* THE SAMPLE'S OWN SIZE, 620, and it only gives that up when the window
     cannot hold it.
     It was cut to a flat 460 to make the stage span fit between the wings,
     which is solving the wrong end of it -- "wait why did u reduce the size of
     the ring". The ring is the centrepiece; everything else gives way.
       620px   what the approved file draws
       64vmin  a short window shrinks it rather than cropping it
       the calc: the stages span 1.08 rings plus a node, the wings want 290
                either side of that, and the sidebar and padding take 288 --
                so this is the largest ring whose stages still clear the wings
       300px   the floor; below the width where that floor is reached, the
                layout collapses and the stages come off the circle */
  --ring-size: max(300px, min(620px, 64vmin, calc((100vw - 798px) / 1.08)));
  --ring-x: 50%;
  --ring-y: 47%;
}
@media (min-width: 1024px) { :root { --ring-x: calc(50% + 7rem); } }

.jv-ax {
  position: fixed; left: var(--ring-x); top: var(--ring-y);
  width: var(--ring-size); height: var(--ring-size);
  translate: -50% -50%;
  /* Inert. The stage nodes turn pointer events back on for themselves, so
     the layer can lie over a page without catching a press meant for it. */
  pointer-events: none;
}
.jv-ax > svg { width:100%; height:100%; display:block; overflow:visible; }
.jv-bg { z-index: 0; }
/* THE READOUT IS BEHIND THE PAGE, NOT OVER IT.
   This was z-index 2, above the content, and at the top of a page that was
   invisible -- the middle column is empty and sized to the node span, so
   nothing overlaps at rest. Scroll down and the band, the stage names and the
   big reading were painted straight across the film rows and the brief's
   questions. His words: "the stages cards are clear and the ring goes in
   background but in other places u havent handled it".
   A stage page always looked right because it has no readout at all -- only
   the backdrop, at z-index 0. So the readout joins it there. The nodes stay
   clickable: at rest there is nothing on top of them. */
.jv-fg { z-index: 0; }

/* THE READOUT'S PAGE KEEPS THE FRAME BUT STOPS CLIPPING.
   A clip-path makes an element the containing block for anything `fixed`
   inside it, so the frame both REPOSITIONED and CROPPED the stage nodes. The
   first fix was to drop the frame on this page -- wrong: the approved file has
   the frame, and without it the composition floats in the middle of nothing.

   So the frame moves to a pseudo-element. Clipping ::after clips only
   ::after, the column stops being a containing block, and the nodes reach the
   viewport. The four corner brackets on ::before are untouched.

   The width comes back too: the sample is a 1320px composition, and at full
   bleed the wings were flung to the far edges of a 1440 screen. */
.content-column:has([data-hero]) {
  max-width: 1360px; border: 0; background: none; clip-path: none;
}
.content-column:has([data-hero])::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--i3) 20%, transparent);
  background: linear-gradient(color-mix(in srgb, #03112b 34%, transparent),
                              color-mix(in srgb, var(--n0) 34%, transparent));
  clip-path: polygon(22px 0, calc(100% - 22px) 0, 100% 22px, 100% calc(100% - 22px),
                     calc(100% - 22px) 100%, 22px 100%, 0 calc(100% - 22px), 0 22px);
}

.jv { position:relative; }
/* The work between the strip and the dock. Padding keeps a page's own panels
   off the two bars without any page knowing they are there. */
.jv-work { padding: 14px 0 16px; }
.jv .frame {
  position:relative; border:1px solid color-mix(in srgb,var(--i3) 20%,transparent);
  padding:14px 18px 18px;
  clip-path:polygon(22px 0,calc(100% - 22px) 0,100% 22px,100% calc(100% - 22px),
    calc(100% - 22px) 100%,22px 100%,0 calc(100% - 22px),0 22px);
  background:linear-gradient(color-mix(in srgb,#03112b 40%,transparent),
                             color-mix(in srgb,var(--n0) 40%,transparent));
}
.jv .fcorner{position:absolute;width:20px;height:20px;border:1px solid var(--i4);opacity:.85}
.jv .fc1{left:5px;top:5px;border-right:0;border-bottom:0}
.jv .fc2{right:5px;top:5px;border-left:0;border-bottom:0}
.jv .fc3{left:5px;bottom:5px;border-right:0;border-top:0}
.jv .fc4{right:5px;bottom:5px;border-left:0;border-top:0}

.jv .hd{display:flex;align-items:center;gap:15px;flex-wrap:wrap;
  border-bottom:1px solid color-mix(in srgb,var(--i3) 15%,transparent);
  padding-bottom:9px;margin-bottom:12px}
.jv .bd{font-weight:700;font-size:15px;letter-spacing:.42em}
.jv .bd i{font-style:normal;color:var(--i4)}
.jv .kv{font-family:var(--font-stat);font-size:8.5px;letter-spacing:.16em;color:var(--muted)}
.jv .kv u{text-decoration:none;color:var(--i4)}
.jv .sp{flex:1}
.jv .lv{display:flex;gap:6px;align-items:center;font-family:var(--font-stat);
  font-size:8.5px;letter-spacing:.2em;color:var(--g3)}
.jv .lv i{width:5px;height:5px;border-radius:50%;background:var(--g3);
  box-shadow:0 0 9px var(--g3);animation:jv-bl 1.6s infinite}
@keyframes jv-bl{50%{opacity:.2}}

/* ══ THE COMPOSITION — AN OPEN MIDDLE ═══════════════════════════════════
   §4 of the spec had wing | core | wing, because the core was drawn on the
   page. R2 moved the stages out around the ring and the ring behind
   everything, so the middle column is now deliberately EMPTY: it is the
   window the instrument is seen through. Widen it and the wings are pushed
   off the nodes; narrow it and a panel sits on top of one.

   The column is centred on the same axis as the ring, so the gap and the
   instrument agree without either being positioned against the other. */
/* The middle is sized FROM the ring, not guessed at, so the stages always
   clear the wings however big the ring has come out. A HUB has no stages
   around its ring -- only the reading inside it -- so its middle needs the
   ring's own width and no more, and its columns get the room instead. */
/* THE MIDDLE CLEARS THE TOP NODE, NOT THE WHOLE SPAN.
   It was the full stage span -- 1.08 rings plus a node -- which left the
   flanks 190px and turned every wing into a column of wrapped fragments.
   The span only matters at the ring's EQUATOR, and the wings sit in the top
   corners: at their height the only node is the one at twelve o'clock, about
   108px wide in the middle. So the flanks get real room, and a node lower
   down reaches over ground the flanks have nothing on.
   How wide, exactly: the widest node that reaches into the wings' band is the
   SECOND one of a seven-node ring, at 51.4 degrees from the top, which sits
   0.42 rings out. Twice that plus a node's width is 0.88 rings + 120px, and
   that covers every count the platform uses -- four shelves, five channels,
   seven steps, eight subjects. It was the full 1.08 span, which left the
   flanks 190px and turned every wing into a column of wrapped fragments.

   The one rule this depends on: a wing's content stays in the top corner.
   Anything long goes below the composition, not in a flank. */
.jv .comp{display:grid;gap:0;align-items:start;
  grid-template-columns:minmax(180px,1fr) calc(var(--ring-size) * 0.88 + 120px) minmax(180px,1fr)}
/* THE OPEN MIDDLE ALSO RESERVES ITS HEIGHT.
   Without this the wings are the only thing in the grid, the grid is 110px
   tall, and the row of buttons under it lands in the middle of the ring --
   which is exactly what it did. The reservation is the node span, so the
   way on sits below the stages instead of across them. */
/* Tall enough that the frame encloses the whole composition -- the ring, the
   stages around it and the way on under them. The frame is the content
   column's, and the column is only as tall as what is in the flow. */
.jv .mid{min-height:calc(var(--ring-size) * 1.32)}
/* Below this the three columns cannot hold the node span, so the wings stack
   and the ring stays behind them -- dense pages already look like this and it
   is correct, not broken. */
@media (max-width:1120px){ .jv .comp{grid-template-columns:1fr} .jv .mid{display:none} }

/* A WING GROWS WITH WHAT IS IN IT. The bracket was a fixed 150px SVG with the
   rows laid over it, which is fine for four figures and useless for a list --
   so it is painted behind the content instead of sizing it. Same shape on
   every page: "isnt the films page brigher in some aspect than the other
   pages?" was two lit wings against empty dark space. */
.jv .wing{position:relative}
.jv .wing svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.jv .pan{position:relative;display:flex;flex-direction:column;justify-content:center;
  gap:9px;padding:15px 16px 15px 28px;min-height:150px}
.jv .wing.right .pan{padding:15px 28px 15px 16px}
/* THE HATCH AND THE EDGE BAR ARE FIXED, NOT STRETCHED.
   They were two paths inside an SVG with preserveAspectRatio="none", so on a
   wing that grew to hold a list the five ticks spread out and sat between the
   rows instead of beside them -- "fix alignment". Drawn here they keep the
   sample's pitch whatever height the wing comes out. */
.jv .pan::before{content:"";position:absolute;left:3px;top:26px;bottom:26px;width:2px;
  background:var(--working);box-shadow:0 0 10px -2px var(--working)}
.jv .wing.right .pan::before{left:auto;right:3px;background:var(--needs-you);
  box-shadow:0 0 10px -2px var(--needs-you)}
.jv .pan::after{content:"";position:absolute;left:9px;top:34px;bottom:34px;width:15px;
  background:repeating-linear-gradient(to bottom,
    color-mix(in srgb,var(--accent) 55%,transparent) 0 1px, transparent 1px 10px)}
.jv .wing.right .pan::after{left:auto;right:9px}
.jv .wing.right .pan{text-align:right}
.jv .wing.right .row{justify-content:flex-end;flex-direction:row-reverse}
.jv .wing.right .rl{text-align:right}
.jv .read{display:flex;flex-direction:column;gap:2px}
.jv .rn{font-family:var(--font-stat);font-size:7px;letter-spacing:.14em;text-transform:uppercase;
  color:color-mix(in srgb,var(--muted) 75%,var(--n0));line-height:1.4}
/* A LONG FIGURE DROPS TO ITS OWN LINE. The wings are what is left of the
   frame once the ring has its span -- about 234px -- and "11 Sept at 23:15"
   beside its label at that width broke across the middle of the date. Short
   figures stay on the label's line, which is the approved file's own layout
   and leaves a film's wings exactly as they were. */
.jv .row{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
/* Only when the figure ENDS the row. A row with a meter after it -- the
   film's DRAWN row -- must not have the figure shoved right and the meter
   crushed against the edge. */
.jv .wing .row > .rv:last-child{margin-left:auto}
.jv .wing.right .row > .rv:last-child{margin-left:0;margin-right:auto}
/* 84px left the value nothing at the width the wings now have -- the middle
   column is the stage span, so the flanks are what is left of the frame. */
.jv .rl{font-family:var(--font-stat);font-size:7.5px;letter-spacing:.18em;color:var(--muted);width:58px}
.jv .rv{font-size:16px;font-weight:700;line-height:1;color:var(--text)}
.jv .rv small{font-size:10px;color:var(--muted);font-weight:400}
/* §5 — the 20-bar coverage strip. 22px tall, 1.5px gap, one bar a scene:
   lit where drawn, dim where not yet, RED where a scene has no picture. It
   was dropped from three builds and it is a signature of the sample. */
.jv .bars{display:flex;gap:1.5px;align-items:flex-end;height:22px;flex:1}
.jv .bars i{flex:1;background:color-mix(in srgb,var(--i2) 55%,transparent);height:55%}
.jv .bars i.h{background:var(--i4);height:100%;box-shadow:0 0 6px color-mix(in srgb,var(--i4) 55%,transparent)}
.jv .bars i.x{background:var(--r3);height:100%}
.jv .mt{height:3px;background:color-mix(in srgb,var(--i1) 70%,transparent);flex:1}
.jv .mt i{display:block;height:100%;background:linear-gradient(90deg,var(--i2),var(--i4));
  box-shadow:0 0 9px color-mix(in srgb,var(--i4) 55%,transparent)}

/* The reading, in the middle of the ring. Inert, so the ring's own detail is
   never hidden behind a click target. */
.jv-fg .hub{position:absolute;inset:0;display:grid;place-items:center;text-align:center;
  z-index:4;pointer-events:none}
.jv-fg .hub b{display:block;font-size:clamp(34px,7vw,56px);font-weight:700;line-height:.82;color:var(--i4);
  text-shadow:0 0 18px color-mix(in srgb,var(--i4) 70%,transparent)}
.jv-fg .hub s{display:block;text-decoration:none;font-family:var(--font-stat);font-size:8px;
  letter-spacing:.34em;color:color-mix(in srgb,var(--muted) 65%,var(--text));margin-top:6px}
/* The reading sits ON the instrument, so the small type needs the ring's own
   detail held back behind it -- a wash of the ground rather than a box, which
   would cut a hole in the thing it is reading from. */
.jv-fg .hub s,.jv-fg .hub em,.jv-fg .hub p{text-shadow:0 0 7px var(--bg),0 0 14px var(--bg)}
.jv-fg .hub em{display:block;font-style:normal;font-size:clamp(13px,2.2vw,18px);font-weight:700;
  letter-spacing:.32em;text-transform:uppercase;margin-top:13px;color:var(--text)}
.jv-fg .hub p{margin:3px 0 0;font-family:var(--font-stat);font-size:7.5px;letter-spacing:.26em;color:var(--o3)}
.jv-fg .hub .ow{display:block;margin-top:9px;font-family:var(--font-stat);font-size:7px;
  letter-spacing:.2em;color:var(--muted);text-transform:uppercase}

/* ══ R2 · THE SEVEN STAGES, AROUND THE RING ══════════════════════════════
   "u said film page u ll put the stages around the rings? instead of the dock
   at bottom."

   Not a bar and not a dock: one node a stage, each at its own angle on the
   circle, with a leader line running inward so the eye joins the name to the
   instrument. The first is at the top and the rest follow clockwise, which is
   pipeline order. Where he is burns orange; what is done reads white; what is
   ahead sits dim; what failed is red -- the same four states as everywhere
   else, so nothing new has to be learnt to read it.

   Angles and radii are computed in film-hud.tsx against the ring box, not
   written here: seven of anything hardcoded in CSS is how a route with six
   steps ends up with a node hanging in space. */
/* WIDE ENOUGH FOR A REAL NAME. At 86px a step label fitted and a channel
   called "Simply Space Things" became three stacked lines that reached down
   into the buttons. 108px and tighter letter-spacing holds almost everything
   in two. */
.jv-fg .node{position:absolute;translate:-50% -50%;z-index:6;width:108px;text-align:center;
  text-decoration:none;pointer-events:auto}
.jv-fg .node .ni{width:30px;height:30px;margin:0 auto 5px;display:grid;place-items:center;
  font-size:13px;line-height:1;color:var(--i1);
  border:1px solid color-mix(in srgb,var(--i3) 28%,transparent);
  background:color-mix(in srgb,var(--n0) 72%,transparent);
  clip-path:polygon(7px 0,100% 0,100% calc(100% - 7px),calc(100% - 7px) 100%,0 100%,0 7px)}
.jv-fg .node .nl{display:block;font-weight:600;font-size:9.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);line-height:1.25;
  /* Two lines at most, so one long name cannot make one node twice the height
     of its neighbours. The whole name is on hover and in the title. */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.jv-fg .node .nn{display:block;font-family:var(--font-stat);font-size:7px;letter-spacing:.2em;
  color:color-mix(in srgb,var(--muted) 70%,var(--n0))}
.jv-fg .node.done .ni{color:var(--g3);border-color:color-mix(in srgb,var(--g3) 30%,transparent)}
.jv-fg .node.done .nl{color:var(--text)}
.jv-fg .node.on .ni{color:var(--o5);border-color:var(--o3);
  background:linear-gradient(color-mix(in srgb,var(--o3) 24%,transparent),transparent);
  box-shadow:0 0 26px -8px var(--o3)}
.jv-fg .node.on .nl{color:var(--o5)}
.jv-fg .node.fail .ni{color:var(--r3);border-color:color-mix(in srgb,var(--r3) 50%,transparent)}
.jv-fg .node.fail .nl{color:var(--r4)}
.jv-fg .node.work .ni{color:var(--i4);border-color:color-mix(in srgb,var(--i4) 45%,transparent)}
.jv-fg .node.work .nl{color:var(--i4)}
.jv-fg .node.dim{opacity:.72}   /* .55 was unreadable — "make sure its readable" */
.jv-fg .node:hover .ni{border-color:var(--i3)}
.jv-fg .node:hover .nl{color:var(--i4)}
.jv-fg .node:focus-visible{outline:1px solid var(--i4);outline-offset:3px}

/* The leader line: from just outside the outermost shell, out to the node.
   transform-origin at its own left edge, so the angle set on it is the angle
   it leaves the circle at. */
.jv-fg .spoke{position:absolute;height:1px;transform-origin:0 50%;z-index:5;
  background:linear-gradient(90deg,color-mix(in srgb,var(--i3) 55%,transparent),transparent)}
.jv-fg .spoke.on{background:linear-gradient(90deg,var(--o3),transparent)}

/* ON A NARROW SCREEN THE STAGES COME OFF THE CIRCLE.
   Mac first -- "mac first, cos process happens here" -- so the arrangement
   above is the real one. But a fixed ring the width of a phone would put
   seven nodes on top of each other and on top of the panels, and the film
   page is one of the screens he opens from the sofa. So below the width the
   composition needs, the layer stops being fixed: the reading becomes a
   heading and the seven become a row of chips in the page, with the ring
   still behind them. Nothing is hidden and nothing overlaps. */
@media (max-width:1120px){
  .jv-fg{position:static;width:auto;height:auto;translate:none;pointer-events:auto;
    display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:6px;margin-top:10px}
  .jv-fg > svg,.jv-fg .spoke{display:none}
  .jv-fg .hub{position:static;grid-column:1/-1;pointer-events:auto}
  .jv-fg .hub b{font-size:40px}
  .jv-fg .node{position:static;translate:none;width:auto;padding:7px 2px;
    border:1px solid color-mix(in srgb,var(--i3) 13%,transparent);
    clip-path:polygon(9px 0,100% 0,100% calc(100% - 9px),calc(100% - 9px) 100%,0 100%,0 9px)}
  .jv-fg .node .ni{margin-bottom:3px}
  .jv-fg .act{position:static;translate:none;grid-column:1/-1;white-space:normal;margin-top:10px}
}

/* ══ R5 · A HUB — HOME AND A CHANNEL ════════════════════════════════════
   "same comment for other nonfilm pages" / "why u didnt do nonfilm pages like
   that". Same frame as the readout: the reading in the ring, the page's own
   two columns either side, the middle left open. No stage nodes -- seven steps
   belong to a film and a hub has none.

   Only the rows are new. Everything else is the composition already above, so
   a third hub costs nothing. */
/* A hub's flanks are the same construction — one grid, both looks. */
/* A page with no flanks: the ring and its ring of destinations, and the height
   they need, so the frame encloses them. */
/* MEASURED, NOT GUESSED. The lowest stage's bottom edge sits 1.20 rings below
   the top of the ring box, so the page reserves 1.22 and the way on lands just
   under it -- clear of the stages and still above the fold on a 950px window.
   Everything here is a multiple of --ring-size, so it holds at any size the
   ring comes out. */
.jv .mid.solo{min-height:calc(var(--ring-size) * 1.32)}
.jv .col{display:flex;flex-direction:column;gap:10px;padding-right:14px}
.jv .col.right{padding-right:0;padding-left:14px}
.jv .hub-below{display:flex;flex-direction:column;gap:14px;margin-top:18px}
/* LANDING CLEAR OF THE STRIP. A fragment scrolls its target to the very top of
   the window, which on these pages puts it under the identity strip. Every
   anchor a node points at leaves room for it. */
[id^="settings-"],.jv .hub-below > [id]{scroll-margin-top:84px}
html{scroll-behavior:smooth}
/* AND WHAT SCROLLS OVER IT MUST COVER IT. A panel is translucent by design,
   which is right over the faint backdrop and wrong over a lit band -- the
   band glowed through the rows. Only the content BELOW a composition is
   thickened, so every other page keeps the theme's own weight. */
/* FULLY opaque, not nearly. At 95% the reading's own glow -- a 56px number
   with a 18px bloom on it -- still came through the panel that had scrolled
   over it. There is nothing behind these worth seeing through them. */
.jv .hub-below .panel,.jv .hub-below .card,.jv .hub-below .table-stack{
  background:linear-gradient(#0a1c3c,var(--n0))}
.jv .col.right{text-align:right}
/* A row is two lines when it needs to be: the name and its one word on the
   first, the sentence on its own underneath. The name and the word share the
   first line and CAN both shrink, so neither can ever overrun the other --
   which is what produced a column of one-word-per-line titles with a sentence
   lying across them. */
.jv .hrow{display:flex;flex-direction:column;gap:2px;padding:5px 0;text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--i2) 12%,transparent)}
.jv .rtop{display:flex;align-items:baseline;gap:10px}
.jv .col.right .rtop{flex-direction:row-reverse}
.jv .run{display:block;font-family:var(--font-stat);font-size:8px;letter-spacing:.14em;
  color:color-mix(in srgb,var(--muted) 75%,var(--n0));text-transform:uppercase;line-height:1.4}
.jv .hrow:last-child{border-bottom:0}
/* A film's title WRAPS rather than truncates. At 290px a column turned "How
   Humans Discovered Smoking" into "HOW HUMANS DISCOVERE..." -- the one thing
   the row exists to say. */
.jv .rl2{font-family:var(--font-stat);font-size:8px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--muted);min-width:0;flex:1;line-height:1.35;overflow-wrap:anywhere}
/* A word or a number. It may shrink -- it used to refuse to, and a long
   sentence here is what crushed the name beside it. */
.jv .rv2{font-weight:700;font-size:13px;line-height:1.15;color:var(--text);
  min-width:0;overflow-wrap:anywhere}
.jv .rv2.needs-you{color:var(--o3)}
.jv .rv2.failed{color:var(--r3)}
a.hrow:hover .rl2{color:var(--i4)}
a.hrow:hover .rv2{color:var(--i5)}

.jv .act{display:flex;gap:11px;justify-content:center;align-items:center;margin-top:13px;flex-wrap:wrap}
/* On the readout the way on hangs off the ring box, under the lowest stage,
   so it can never land across the instrument. 116% clears a node's own
   height; the row turns pointer events back on for itself. */
.jv-fg .act{position:absolute;left:50%;top:112%;translate:-50% 0;margin-top:0;
  pointer-events:auto;white-space:nowrap;flex-wrap:nowrap;z-index:6}
.jv .warn{font-family:var(--font-stat);font-size:8.5px;letter-spacing:.2em;color:var(--o3)}

/* ══ THE STEP BAR WEARS THE DOCK'S DESIGN ════════════════════════════════
   "u put that bottom bar design to the current ones on top for the stages."

   So the dock is not repeated at the foot of a stage page — the row that is
   already at the top of it becomes the dock: angular chips, a lit rail on the
   one you are standing on, the state's mark in its own colour. One navigation,
   where it already was. */
.step-bar { gap: 6px; }
.step-chip {
  border-radius: 0 !important;
  padding: 8px 14px !important;
  border: 1px solid color-mix(in srgb, var(--i3) 14%, transparent);
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px),
                     calc(100% - 9px) 100%, 0 100%, 0 9px);
  background: linear-gradient(color-mix(in srgb, var(--i1) 24%, transparent), transparent);
  font-family: var(--font-display);
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); text-decoration: none;
}
.step-chip:hover { border-color: var(--i3); color: var(--text); }
.step-chip[data-state="done"] { color: var(--text); }
.step-chip[data-state="failed"] { color: var(--r3); border-color: var(--failed-edge); }
.step-chip.on {
  border-color: var(--o3); color: var(--o5);
  background: linear-gradient(color-mix(in srgb, var(--o3) 24%, transparent), transparent);
  box-shadow: 0 0 26px -8px var(--o3);
}
.step-chip.dim { opacity: .5; }
/* the number is instrument type, not body text */
.step-chip .stat { font-family: var(--font-stat); font-size: 9px; letter-spacing: .14em; }
