/* ============================================================================
 * ffv-modal-theme.css — FFV Modal Renaissance shared theme layer (S1).
 *
 * forging-modal-renaissance S1 (2026-07-21). The CSS half of the chassis kit
 * (js/core/ffv-chassis.js): per-theme design tokens as CSS custom properties,
 * the `.ffv-chassis-layer` mechanics, the ambient mote field, and the
 * rectangular mask-composite rim FALLBACK (used whenever the SVG chassis is
 * not stamped — mobile, reduced capability, or a theme without a silhouette).
 *
 * Coherence rules (plan D1): same glass depth, same rim technique, same
 * corner-irregularity degree across themes; motion calmer than the vessel;
 * prefers-reduced-motion respected; no particles over text wells; font floor
 * = Playfair Display (display) / Source Sans 3 (body).
 * ========================================================================== */

/* ── Theme tokens ───────────────────────────────────────────────────────── */

/* The Biographer's Study — a writing desk at night. Warm lamplight pooled on
 * handmade paper, sepia ink, the family's magenta only glinting at the rim. */
.ffv-theme-biographer {
    --ffv-gold: #f0c66a;          /* gold leaf */
    --ffv-amber: #d99a3d;         /* lamplight amber */
    --ffv-sepia: #8a5a2e;         /* burnished sepia */
    --ffv-orchid: #ef3fa5;        /* the one family glint */
    --ffv-desk-1: #2b1d12;        /* deep umber */
    --ffv-desk-2: #141322;        /* night navy */
    --ffv-page: #f6eedd;          /* handmade paper */
    --ffv-page-deep: #eadbba;     /* page shadow edge */
    --ffv-ink: #35291a;           /* sepia ink */
    --ffv-ink-soft: #6d5a3e;      /* faded ink */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(240, 198, 106, 0.62), rgba(217, 154, 61, 0.5) 30%,
        rgba(138, 90, 46, 0.55) 56%, rgba(239, 63, 165, 0.4) 78%,
        rgba(240, 198, 106, 0.55));
    --ffv-glass-bg: linear-gradient(155deg,
        rgba(43, 29, 18, 0.95), rgba(29, 22, 34, 0.97) 40%,
        rgba(18, 21, 39, 0.97) 72%, rgba(36, 20, 7, 0.94));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* Vessel-satellite (neutral) — the generic bespoke child's existing look,
 * formalized as tokens. S2 flips .fergi-bespoke-shell onto these. */
.ffv-theme-satellite {
    --ffv-rim-gradient: linear-gradient(120deg,
        rgba(239, 63, 165, 0.55), rgba(157, 95, 224, 0.45),
        rgba(79, 155, 196, 0.5), rgba(64, 226, 210, 0.4));
    --ffv-glass-bg: linear-gradient(160deg,
        rgba(34, 22, 44, 0.97), rgba(16, 14, 34, 0.985));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* The Cartographer of a Life (What-I-Know) — a star-chart plate. The KG's
 * view of any person: cool ink-navy glass, azure→aqua→violet rim, citation
 * stars fixed in the margins. "What the Vault knows, and how it knows it." */
.ffv-theme-kg {
    --ffv-azure: #35aae8;         /* chart azure */
    --ffv-aqua: #40e2d2;          /* graticule aqua */
    --ffv-violet: #9d5fe0;        /* deep-sky violet */
    --ffv-starlight: #bfe7ff;     /* pale star white */
    --ffv-chart-1: #0c1424;       /* ink navy */
    --ffv-chart-2: #16123a;       /* far-corner violet-navy */
    --ffv-chart-text: #dce9f7;    /* body text on the plate */
    --ffv-chart-muted: #93aecb;   /* secondary text */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(53, 170, 232, 0.6), rgba(64, 226, 210, 0.5) 33%,
        rgba(47, 143, 214, 0.5) 60%, rgba(157, 95, 224, 0.5) 85%,
        rgba(53, 170, 232, 0.55));
    --ffv-glass-bg: linear-gradient(145deg,
        rgba(12, 20, 36, 0.96), rgba(16, 26, 51, 0.97) 38%,
        rgba(13, 18, 41, 0.97) 72%, rgba(22, 18, 58, 0.95));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* The Archivist's Light Table (UMI — the Heart) — warm archival glass. A
 * bevel-cut mat plate on a light table: ivory→copper→bronze rim, one orchid
 * glint, a projector-beam wash from the head. directing-desktop-scenes S6. */
.ffv-theme-umi {
    --ffv-copper: #c97b4a;        /* copper rim */
    --ffv-bronze: #8a5a2e;        /* burnished bronze */
    --ffv-ivory: #f2e8d8;         /* archival ivory */
    --ffv-orchid: #ef3fa5;        /* the one family glint */
    --ffv-case-1: #241610;        /* warm case umber */
    --ffv-case-2: #131018;        /* case night */
    --ffv-card: #f4ecdb;          /* the catalog card (info pane) */
    --ffv-card-deep: #ece0c6;     /* card header band */
    --ffv-card-ink: #33261a;      /* ink on the card */
    --ffv-card-soft: #6d5a3e;     /* faded ink */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(242, 227, 194, 0.6), rgba(201, 123, 74, 0.5) 30%,
        rgba(138, 90, 46, 0.5) 56%, rgba(239, 63, 165, 0.38) 80%,
        rgba(226, 178, 120, 0.55));
    --ffv-glass-bg: linear-gradient(150deg,
        rgba(36, 22, 16, 0.95), rgba(23, 17, 26, 0.97) 42%,
        rgba(19, 16, 24, 0.97) 72%, rgba(38, 20, 10, 0.94));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* umi chassis strokes: the beam wash rides the shared .ffvc-wash class. */
.ffvc-umi .ffvc-wash { opacity: 1; }

/* The Dressing Room (curated set + official headshot designer) — a
 * performer's dressing room before the show. Warm rose and brass, the vanity
 * mirror's bulb-light pooled on the wardrobe rail, the one orchid family
 * glint. cssOnly family member (craft journal §2) — no SVG chassis; the
 * bespoke shell's rectangular rim carries the dress.
 * unbifurcating-vault-surfaces S7 (curating-member-portrayal). */
.ffv-theme-dressing {
    --ffv-rose: #d98a9c;          /* powder rose */
    --ffv-brass: #d9b36a;         /* vanity brass */
    --ffv-bulb: #ffd9a0;          /* mirror-bulb warm */
    --ffv-orchid: #ef3fa5;        /* the one family glint */
    --ffv-room-1: #2a161d;        /* rose-black room */
    --ffv-room-2: #16101a;        /* wing shadow */
    --ffv-dr-text: #f3e7e0;       /* body text in the room */
    --ffv-dr-muted: #c2a3a4;      /* secondary text */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(255, 217, 160, 0.6), rgba(217, 179, 106, 0.5) 28%,
        rgba(217, 138, 156, 0.5) 55%, rgba(239, 63, 165, 0.42) 80%,
        rgba(255, 217, 160, 0.55));
    --ffv-glass-bg: linear-gradient(150deg,
        rgba(42, 22, 29, 0.96), rgba(30, 18, 26, 0.97) 40%,
        rgba(22, 16, 26, 0.97) 72%, rgba(40, 22, 20, 0.95));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* The Reading Room (Stories modal) — the vault's library at night. Brass rim
 * with a bottle-green and oxblood passage, banker's-lamp pool, a shelf of
 * faint spines along the foot. Kin to the Biographer's folio. */
.ffv-theme-library {
    --ffv-brass: #d9b36a;         /* brass lamp light */
    --ffv-bottle: #2c4a38;        /* bottle green */
    --ffv-oxblood: #7c3328;       /* leather spines */
    --ffv-orchid: #ef3fa5;        /* the one family glint */
    --ffv-room-1: #122018;        /* green night */
    --ffv-room-2: #1e160c;        /* walnut shadow */
    --ffv-page: #f7f0df;          /* the reading page */
    --ffv-page-deep: #efe4c9;     /* page shadow edge */
    --ffv-ink: #35291a;           /* reading ink */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(233, 207, 154, 0.6), rgba(217, 179, 106, 0.5) 26%,
        rgba(84, 120, 88, 0.5) 52%, rgba(124, 51, 40, 0.5) 74%,
        rgba(239, 63, 165, 0.36) 88%, rgba(217, 179, 106, 0.5));
    --ffv-glass-bg: linear-gradient(150deg,
        rgba(18, 32, 24, 0.96), rgba(20, 26, 20, 0.97) 40%,
        rgba(16, 20, 16, 0.97) 70%, rgba(30, 22, 12, 0.95));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* library chassis strokes: the shelf of spines (kit paints geometry; CSS
 * carries weights, colors, opacities). Whisper volume — never competes. */
.ffvc-library .ffvc-shelf        { fill: none; stroke: #d9b36a; }
.ffvc-library .ffvc-shelf-spines { stroke-width: 2.6; opacity: 0.09; stroke-linecap: round; }
.ffvc-library .ffvc-shelf-lean   { stroke-width: 2; opacity: 0.07; stroke-linecap: round; }
.ffvc-library .ffvc-shelf-line   { stroke-width: 1.3; opacity: 0.13; }
.ffv-chassis-layer.ffvc-compact .ffvc-shelf { display: none; }

/* The Picture Palace (story playback surface) — the vault's movie theatre at
 * night. Velvet-black house, marquee-gold → crimson → bordeaux rim with the
 * one orchid glint, proscenium arch, curtain folds in the side margins,
 * footlights along the apron, dust in the projector beam.
 * directing-desktop-scenes S7 (R24). */
.ffv-theme-theatre {
    --ffv-marquee: #ecc76f;       /* marquee gold */
    --ffv-brass-aged: #c2903f;    /* aged brass */
    --ffv-velvet: #8e2f36;        /* crimson velvet */
    --ffv-bordeaux: #5f1f26;      /* deep bordeaux */
    --ffv-orchid: #ef3fa5;        /* the one family glint */
    --ffv-house-1: #2a1216;       /* velvet crimson-black */
    --ffv-house-2: #120d13;       /* house night */
    --ffv-rim-gradient: linear-gradient(125deg,
        rgba(236, 199, 111, 0.6), rgba(194, 144, 63, 0.5) 30%,
        rgba(142, 47, 54, 0.5) 55%, rgba(95, 31, 38, 0.5) 78%,
        rgba(239, 63, 165, 0.36) 87%, rgba(236, 199, 111, 0.5));
    --ffv-glass-bg: linear-gradient(150deg,
        rgba(42, 18, 22, 0.96), rgba(25, 15, 22, 0.97) 40%,
        rgba(18, 13, 19, 0.97) 72%, rgba(36, 16, 22, 0.95));
    --ffv-display-font: 'Playfair Display', Georgia, serif;
    --ffv-body-font: 'Source Sans 3', 'Inter', sans-serif;
}

/* theatre chassis strokes: arch, curtains, footlights (kit paints geometry;
 * CSS carries weights, colors, opacities). Whisper volume — the stage wins. */
.ffvc-theatre .ffvc-wash         { opacity: 1; }
.ffvc-theatre .ffvc-arch         { fill: none; stroke: #ecc76f; }
.ffvc-theatre .ffvc-arch-line    { stroke-width: 1.6; opacity: 0.12; }
.ffvc-theatre .ffvc-curtain      { fill: none; stroke: #8e2f36; }
.ffvc-theatre .ffvc-curtain-fold { stroke-width: 2.4; opacity: 0.14; stroke-linecap: round; }
.ffvc-theatre .ffvc-curtain-hem  { stroke-width: 1.6; opacity: 0.1; stroke-linecap: round; }
.ffvc-theatre .ffvc-foots        { stroke: none; }
.ffvc-theatre .ffvc-foot-lamp    {
    fill: #f2d791;
    opacity: 0.16;
    animation: ffvc-foot-glow 12s ease-in-out infinite alternate;
}
.ffvc-theatre .ffvc-foot-glow    { fill: none; stroke: #f2d791; stroke-width: 7; opacity: 0.05; }
.ffv-chassis-layer.ffvc-compact .ffvc-curtain,
.ffv-chassis-layer.ffvc-compact .ffvc-foots,
.ffv-chassis-layer.ffvc-compact .ffvc-arch { display: none; }
@keyframes ffvc-foot-glow {
    from { opacity: 0.1; }
    to   { opacity: 0.2; }
}
@media (prefers-reduced-motion: reduce) {
    .ffvc-theatre .ffvc-foot-lamp { animation: none !important; opacity: 0.14; }
}

/* Mounted-vessel pattern (R20): pane-filling tenants keep their geometry
 * contract; the chassis floats at POSITIVE inset within the element's own
 * night room instead of overhanging a floating shell. */
.ffv-chassis-layer.ffvc-umi     { inset: 8px 12px 10px; }
.ffv-chassis-layer.ffvc-library { inset: 8px 14px 10px; }
.ffv-chassis-layer.ffvc-theatre { inset: 8px 12px 10px; }

/* ── The theatre host: #view-story-presentation (the in-app playback view).
 *    R24: the vessel dresses the playback SURFACE in both pane states — in
 *    the normal state it frames the App-Panel view; under pane-maximized the
 *    view IS the viewport, so the proscenium becomes the takeover chrome.
 *    FrameController single-tenancy is untouched: the chassis is a passive
 *    layer riding the container. All rules scoped under .ffvc-framed, which
 *    only ever stamps on desktop (mobile + /about/ + /stories/<slug>/ are
 *    byte-identical — R23). The player's chrome (deck, rail, subtitles,
 *    carousel, countdown) insets inside the silhouette; the geometry
 *    relationships between them are preserved, shifted by the frame band. */
#view-story-presentation.ffv-theme-theatre.ffvc-framed {
    position: relative;
    background:
        radial-gradient(ellipse 80% 60% at 50% 8%,
            rgba(64, 26, 22, 0.5), rgba(10, 6, 10, 0.95) 75%),
        #0a060a;
}
#view-story-presentation.ffvc-framed .pres-deck {
    top: 48px; left: 50px; right: 50px; bottom: 64px;
}
#view-story-presentation.ffvc-framed.has-carousel .pres-deck {
    bottom: calc(64px + var(--pres-carousel-h, 140px));
}
#view-story-presentation.ffvc-framed .pres-controls { right: 56px; }
#view-story-presentation.ffvc-framed .pres-subtitles {
    bottom: 64px; left: 50px; right: 106px;
}
#view-story-presentation.ffvc-framed .pres-media-carousel {
    bottom: 140px; left: 62px; right: 118px;
}
#view-story-presentation.ffvc-framed .pres-countdown { bottom: 112px; }

/* kg chassis strokes: the graticule + pole star (kit paints geometry; CSS
 * carries weights, colors, opacities, and the slow life). */
.ffvc-kg .ffvc-wash      { opacity: 1; }
.ffvc-kg .ffvc-graticule { fill: none; stroke: #40e2d2; }
.ffvc-kg .ffvc-grat-arc  { stroke-width: 1; opacity: 0.11; }
.ffvc-kg .ffvc-grat-ray  { stroke-width: 0.8; opacity: 0.07; }
.ffvc-kg .ffvc-pole-star {
    stroke: #bfe7ff;
    stroke-width: 1.4;
    stroke-linecap: round;
    fill: #bfe7ff;
    opacity: 0.8;
    animation: ffvc-pole-breathe 9s ease-in-out infinite alternate;
}
/* compact plates lose the graticule with the other flourishes */
.ffv-chassis-layer.ffvc-compact .ffvc-graticule { display: none; }

/* ── The kg dress on the bespoke shell (What-I-Know rides a Fergi bespoke
 *    child). Unframed = rectangular fallback in chart colors; once the plate
 *    stamps (.ffvc-framed) the SVG takes over painting and the box vanishes,
 *    exactly like the Biographer's Study. ─────────────────────────────────── */
.ffv-theme-kg .fergi-bespoke-shell {
    background: var(--ffv-glass-bg);
    border-color: rgba(53, 170, 232, 0.35);
    box-shadow:
        0 0 0 1px rgba(64, 226, 210, 0.12),
        0 18px 60px rgba(4, 8, 18, 0.65),
        0 0 42px rgba(53, 170, 232, 0.14);
}
.ffv-theme-kg .fergi-bespoke-shell::before {
    background: var(--ffv-rim-gradient);
}
.ffv-theme-kg .fergi-bespoke-header {
    background: linear-gradient(90deg,
        rgba(53, 170, 232, 0.16), rgba(64, 226, 210, 0.09), rgba(157, 95, 224, 0.14));
    border-bottom: 1px solid rgba(53, 170, 232, 0.22);
}
.ffv-theme-kg .fergi-bespoke-title {
    font-family: var(--ffv-display-font);
    font-weight: 600;
    letter-spacing: 0.015em;
    color: #dff1ff;
    text-shadow: 0 0 20px rgba(53, 170, 232, 0.25);
}
.ffv-theme-kg .fergi-bespoke-close:hover { background: rgba(53, 170, 232, 0.3); }

.ffv-theme-kg .fergi-bespoke-shell.ffvc-framed {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    overflow: visible;
    border-radius: 0;
    padding: 12px 20px 14px 16px;   /* inset content from the irregular limb */
}
.ffv-theme-kg .fergi-bespoke-shell.ffvc-framed::before { display: none; }
/* .ffs-handle excluded: the resize band keeps its own absolute edge
   placement (fleet resize-chrome contract, spatial-manager.css).
   ⛔ THE EXCLUSION NOW ALSO CARRIES THE ARMED BRACKETS (armed-bracket-perimeter
   S2). The corner cues are `.ffs-handle::after`, so this `:not()` is the only
   thing keeping them above the lifted content — drop it here and the brackets
   go dark in THIS room while staying lit everywhere else, which reads as
   "fixed in some rooms". There are FIVE content-lift sites in app/css
   (biography-modal, dressing-room, ffv-modal-theme, unified-media-modal,
   stories); they are one edit, and window-manager.smoke.cjs sweeps all of
   them so the set cannot drift by hand. */
.ffv-theme-kg .fergi-bespoke-shell > :not(.ffv-chassis-layer):not(.ffs-handle) {
    position: relative;
    z-index: 1;
}
.ffv-theme-kg .fergi-bespoke-shell.ffvc-framed .fergi-bespoke-header {
    background: none;
    border-bottom-color: rgba(64, 226, 210, 0.16);
}
/* a deeper night behind the chart, matching the Study's room dim */
.ffv-theme-kg.fergi-bespoke-modal::before {
    background: rgba(6, 10, 20, 0.56);   /* ::before — the App-Panel scrim, so the
        Header and Control Panel rail stay legible (issue #6, S4 2026-08-13). */
}

/* ── Chassis layer mechanics ────────────────────────────────────────────── */

/* The layer sits BEHIND the shell's content, overhanging the shell rect so
 * the irregular silhouette breathes past the rectangular box. The host theme
 * (e.g. biography-modal.css) makes its shell transparent + overflow:visible
 * once `.ffvc-framed` is stamped, and lifts real content to z-index:1. */
.ffv-chassis-layer {
    position: absolute;
    inset: -24px;
    z-index: 0;
    pointer-events: none;
    /* S7 perf: isolate the blur-filtered SVG's layout/style work from the
       host document (no paint containment — the silhouette overflows). */
    contain: layout style;
}

/* S7 perf — multi-vessel drag: while any managed drag/resize gesture is live
 * (body.ffs-no-select rides every FFASpatial pointer gesture), the ambient
 * life rests so the blur-filtered chassis SVGs stay off the pointer's
 * critical path. The frames keep their last painted breath; motion resumes
 * on release. */
body.ffs-no-select .ffvc-mote,
body.ffs-no-select .ffvc-rim-glow,
body.ffs-no-select .ffvc-pole-star,
body.ffs-no-select .ffvc-foot-lamp {
    animation-play-state: paused;
}

/* ── S3 perf — TEXT ENTRY GETS THE SAME REST AS DRAGGING ──────────────────────
 * unsilencing-vault-surfaces S3, D3.3/D3.4. Joe /listen 2026-08-05, Issue #3:
 * typing in the UMI commentary box lags.
 *
 * It is PAINT, not script. There is no per-keystroke handler on that box —
 * umOpenCommentary() binds only keydown for Ctrl/Cmd+Enter, and the one global
 * `input` listener (activity-logger.js) increments a counter on a 2s flush. The
 * cost is the chassis the box sits inside: measured live behind the commentary
 * textarea at v1.0.220, 11 drifting motes each carrying two box-shadow glows,
 * a breathing rim glow, and three feGaussianBlur filters (stdDeviation 6 / 2.8
 * / 11) — 12 elements animating continuously while the caret blinks.
 *
 * MEASURED, not asserted (logs/unsilencing-vault-surfaces/fixtures/
 * s3-typing-latency.mjs — real keystrokes, double-rAF input→paint, both arms
 * interleaved in one page, N=240 keystrokes per arm, vsync-locked at 16.7ms):
 *
 *     input→paint p50   31.4ms → 27.5ms      (-12.4%)
 *     input→paint mean  32.1ms → 27.7ms      (-13.7%)
 *     frames over 32ms  126/417 → 76/433     (30.2% → 17.6% of frames dropped)
 *
 * ⛔ NOT `body.ffs-no-select`, which is the obvious reuse and would be a bug.
 * spatial-manager.css:36-40 gives that class `user-select: none !important` on
 * the body AND EVERY DESCENDANT. It is a DRAG state; applying it on text focus
 * would kill selection inside the very textarea being typed into.
 *
 * ⛔ NOT `contain: paint` either. The chassis layer overflows its shell by 24px
 * on purpose (inset: -24px, above) and deliberately takes only `contain: layout
 * style`. Paint containment would clip the silhouette that is the whole point.
 *
 * WHY PURE CSS AND NO JS STATE. A focusin/focusout pair stamping a body class
 * is the same shape as the drag state, and it can DESYNC — a focusout that
 * never fires (node removed while focused, modal torn down mid-edit) leaves the
 * ambient life dead for the rest of the session, silently. That is precisely
 * this train's defect class. `:has()` cannot desync: it is a live query, so the
 * state is derived from the document rather than tracked alongside it, and
 * there is nothing to leak and no listener to remove. Where :has() is
 * unsupported the rule is simply dropped and behaviour is exactly today's —
 * fails open, never closed.
 *
 * The scope is the DOCUMENT, not the focused vessel, and that is deliberate:
 * several themed vessels can be open on the canvas at once, and every one of
 * them is competing for the same compositor while the member types into one.
 * Pausing only the focused vessel would leave the others painting.
 *
 * Checkboxes, radios, buttons and ranges are excluded — focusing those is not
 * text entry and carries no repeated input→paint cost to protect. */
body:has(textarea:focus,
         [contenteditable="true"]:focus,
         [contenteditable=""]:focus,
         input:not([type]):focus,
         input[type="text"]:focus,
         input[type="search"]:focus,
         input[type="email"]:focus,
         input[type="url"]:focus,
         input[type="tel"]:focus,
         input[type="password"]:focus,
         input[type="number"]:focus)
    :is(.ffvc-mote, .ffvc-rim-glow, .ffvc-pole-star, .ffvc-foot-lamp) {
    animation-play-state: paused;
}
.ffv-chassis-layer .ffvc-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

/* Silhouette strokes (paint URLs are set inline by the kit — per-instance
 * gradient ids; CSS carries the weights, opacities, and life). */
.ffvc-rim-glow {
    stroke-width: 16;
    opacity: 0.34;
    animation: ffvc-rim-breathe 7s cubic-bezier(0.22, 0.8, 0.24, 1) infinite alternate;
}
.ffvc-body   { stroke-width: 7; }
.ffvc-lip    { stroke-width: 2.2; opacity: 0.9; }
.ffvc-hl     { stroke-width: 2; opacity: 0.6; }
.ffvc-gutter { opacity: 0.5; }
.ffvc-lamp   { opacity: 1; }

/* Compact shells (< 700px wide): drop the side flourishes so the silhouette
 * never crowds the content. */
.ffv-chassis-layer.ffvc-compact .ffvc-gutter,
.ffv-chassis-layer.ffvc-compact .ffvc-motes { display: none; }

/* ── Ambient motes (dust in the lamplight; calmer than the vessel) ──────── */
.ffvc-motes {
    position: absolute;
    inset: 0;
    overflow: visible;
    pointer-events: none;
}
.ffvc-mote {
    position: absolute;
    width: var(--mote-size);
    height: var(--mote-size);
    border-radius: 50%;
    background: currentColor;
    opacity: 0.4;
    box-shadow: 0 0 6px currentColor, 0 0 14px currentColor;
    animation: ffvc-mote-drift var(--mote-duration) ease-in-out infinite alternate;
}

/* ── Rectangular rim fallback (mask-composite; the proven bespoke-shell
 *    technique) — for shells wearing a theme WITHOUT a stamped SVG chassis
 *    (mobile sheet, future rectangular members of the family). Hosts opt in
 *    by putting .ffv-rim on the shell; it hides once the chassis stamps. ── */
.ffv-rim {
    position: relative;
}
.ffv-rim::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 2px;
    background: var(--ffv-rim-gradient);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    pointer-events: none;
    opacity: 0.75;
}
.ffv-rim.ffvc-framed::before { display: none; }

/* ── Motion discipline ──────────────────────────────────────────────────── */
@keyframes ffvc-mote-drift {
    from { transform: translate3d(0, 0, 0) scale(0.85); opacity: 0.12; }
    to   { transform: translate3d(var(--mote-dx), var(--mote-dy), 0) scale(1.15); opacity: 0.5; }
}
@keyframes ffvc-rim-breathe {
    from { opacity: 0.24; }
    to   { opacity: 0.44; }
}

/* Pulse-mode motes: fixed stars that breathe in place (the Cartographer's
 * citation stars) — no drift, a slow twinkle. */
.ffvc-mote--pulse {
    animation: ffvc-star-pulse var(--mote-duration) ease-in-out infinite;
    box-shadow: 0 0 4px currentColor, 0 0 10px currentColor;
}
@keyframes ffvc-star-pulse {
    0%, 100% { opacity: 0.16; transform: scale(0.8); }
    50%      { opacity: 0.75; transform: scale(1.25); }
}
@keyframes ffvc-pole-breathe {
    from { opacity: 0.55; }
    to   { opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
    .ffvc-mote,
    .ffvc-rim-glow,
    .ffvc-pole-star { animation: none !important; }
    .ffvc-mote      { opacity: 0.22; }
    .ffvc-mote--pulse { opacity: 0.35; }
    .ffvc-rim-glow  { opacity: 0.28; }
    .ffvc-pole-star { opacity: 0.7; }
}

/* ── Full-display takeover rung (Track B5, modal-renaissance S7) ─────────
 * The top ladder rung of the folio and the bespoke chassis is a TAKEOVER:
 * FFASizeLadder sets .ffa-display-max on the shell, fills it 100vw×100vh,
 * and FrameController slides the Header + Control Panel away. Doubled class
 * beats every single-class host cap (max-height etc.) without !important. */
.ffa-display-max.ffa-display-max {
    border-radius: 0;
    max-width: none;
    max-height: none;
}
/* The frame's tenant is not a floating window — the resize grip rests.
 * ⛔ TWO MAXIMISED STATES, ONE RULE (D5, armed-bracket-perimeter S2). FFASpatial
 * refuses the resize gesture under EITHER class (`displayMaxed`:
 * `.ffa-display-max` from FFASizeLadder, `.ffw-maximized` from
 * FFVWindowManager) — but only the first ever hid the grips, so a
 * `.ffw-maximized` room showed four corner brackets advertising a resize it
 * would silently refuse. S2 gave the affordance a voice (the brackets arm on
 * approach), which would have made that lie louder rather than quieter. Edit
 * these two selectors TOGETHER; splitting them is how a promise comes back in
 * one maximised state and not the other. */
.ffa-display-max > .ffs-handle,
.ffw-maximized > .ffs-handle { display: none; }
/* The room falls away: overlay padding off so the shell IS the display,
 * and the ground behind the silhouette's corners deepens to true night —
 * no page bleed at the corner reveals. */
.bio-modal:has(> .ffa-display-max),
.fergi-bespoke-modal:has(> .ffa-display-max) { padding: 0; }
.bio-modal:has(> .ffa-display-max) {
    background:
        radial-gradient(ellipse 90% 70% at 44% 30%,
            rgba(64, 42, 16, 0.30), rgba(10, 8, 16, 0.94) 78%),
        rgba(10, 8, 16, 0.9);
}
.fergi-bespoke-modal:has(> .ffa-display-max) { background: rgba(8, 7, 16, 0.93); }
/* S8 polish: at full display the folio's two pages stretch to the floor of
 * the shell — an open book fills its desk, no dead glass below short pages —
 * and the spread keeps a reading measure instead of running the full 100vw. */
.bio-modal-shell.ffa-display-max .bio-modal-body {
    display: flex;
    flex-direction: column;
}
.bio-modal-shell.ffa-display-max .bio-modal-panes {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    max-width: 1680px;
    margin: 0 auto;
}
/* The frame's round pane-restore button (z 14999) would sit on the shell's
 * own top-right controls — during a modal takeover it waits mid-right,
 * dressed in the family glass so it reads against any chassis rim. */
body.ffa-display-takeover .pane-restore-btn {
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    background: rgba(16, 14, 30, 0.78);
    border: 1px solid rgba(125, 127, 181, 0.45);
    box-shadow: 0 4px 18px rgba(6, 4, 14, 0.5);
}
body.pane-maximized.ffa-display-takeover .pane-restore-btn { opacity: 0.55; }
body.ffa-display-takeover .pane-restore-btn:hover {
    transform: translateY(-50%) scale(1.1);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Ambient Fergi AI input widget — unsilencing-vault-surfaces S6/D6.10
   Joe directive 2026-08-05: "this same icon and design should be applied to
   the Ambient Fergi AI input widget that should appear in most modals."

   Styled here, on the shared modal theme sheet, rather than in
   unified-media-modal.css — the widget is destined for MOST modals, and its
   look is the vault's, not the UMI's. The markup lands in one host on this
   pass (lifecycle proof first); the styling is already host-agnostic, keyed
   only on .um-ambient-fergi, so the deferred generalisation is a markup
   change and not a second stylesheet.
   ═══════════════════════════════════════════════════════════════════════════ */

.um-ambient-fergi {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    margin-top: 10px;
    padding: 7px 10px;
    border-radius: 999px;
    border: 1px solid rgba(240, 198, 106, 0.28);
    background: rgba(20, 19, 34, 0.42);
    transition: border-color 160ms ease, background 160ms ease;
}

.um-ambient-fergi:focus-within {
    border-color: rgba(240, 198, 106, 0.62);
    background: rgba(20, 19, 34, 0.60);
}

.um-ambient-fergi-orb {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    opacity: 0.9;
}

.um-ambient-fergi-input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: transparent;
    color: var(--ffv-page, #f6eedd);
    font-family: var(--ffv-body-font, sans-serif);
    font-size: 0.92rem;
    padding: 2px 0;
}

.um-ambient-fergi-input::placeholder {
    color: rgba(246, 238, 221, 0.45);
    font-style: italic;
}

/* The widget carries its own focus ring on the pill (:focus-within above), so
   the inner outline would double it. */
.um-ambient-fergi-input:focus { outline: none; }

.um-ambient-fergi-go {
    flex: 0 0 auto;
    border: 1px solid rgba(240, 198, 106, 0.35);
    border-radius: 999px;
    background: rgba(240, 198, 106, 0.12);
    color: var(--ffv-gold, #f0c66a);
    font-family: var(--ffv-body-font, sans-serif);
    font-size: 0.8rem;
    letter-spacing: 0.04em;
    padding: 4px 12px;
    cursor: pointer;
    transition: background 160ms ease;
}

.um-ambient-fergi-go:hover { background: rgba(240, 198, 106, 0.24); }
