Files
deepdrft/DeepDrftPublic.Client/Pages/About.razor
T
2026-06-22 22:41:39 -04:00

370 lines
19 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@page "/about"
@using DeepDrftPublic.Client.Controls
@implements IAsyncDisposable
@inject IJSRuntime JsRuntime
<PageTitle>The Collective - Deep DRFT</PageTitle>
@* ──────────────────────────────────────────────────────────────────────────────
THE LINER NOTES — a numbered three-movement editorial essay.
This page deliberately does NOT reuse Home's section grammar (centred dividers,
symmetric 4/8 splits, the medium-card grid). Its backbone is a persistent left
"rail" — a continuous vertical hairline (the narrative spine) carrying oversized
Bodoni movement numerals (01/02/03) and mono marginalia — with the content column
running asymmetrically to its right. Movement boundaries are rendered as a
self-contained SVG waveform stroke (the DeepDrft visualizer motif, hand-authored
here — NOT the live WaveformVisualizer component).
The numeral active-highlight (green on the movement in view) is progressive
enhancement via IntersectionObserver: without JS the numerals still render
statically in low-opacity navy. See Interop/about/about-rail.ts.
────────────────────────────────────────────────────────────────────────────── *@
@* ── HERO — the page opener. Reuses the .hero-* type scale with About's own words.
NOT DeepDrftHero (that hard-codes the Deep/DRFT masthead + streaming CTA). ── *@
<section class="hero pb-20">
<MudGrid Spacing="0">
<MudItem xs="12" md="6">
<div class="hero-left">
<div class="hero-eyebrow @AnimClass">Charleston, South Carolina</div>
<h1 class="hero-title @AnimClass">The<br /><em>Collective</em></h1>
<p class="hero-desc @AnimClass">
Two people, many hats. We bring the heart and soul of Midwest deep house to Charleston &mdash; informed by the founders of the style, and promising to push it forward.
</p>
</div>
</MudItem>
<MudItem xs="12" md="6">
@* IMG SLOT A — hero duo portrait, inset within the content column. *@
<div class="hero-image-pane">
<ParallaxImage Image1="img/dd-duo-2-bw.jpg"
Image2="img/dd-duo-2.jpeg"
Alt1="Deep DRFT — two-person electronic music collective"
NaturalWidth="2048"
NaturalHeight="1365"
WindowHeightFraction="0.9"
ImageHeight="auto"
ImageWidth="100%"
ParallaxSpeed="0.25" />
</div>
</MudItem>
</MudGrid>
</section>
@* ════════════════ MOVEMENT ONE — THE PEOPLE (pathos) ════════════════ *@
<div class="movement" data-movement="1" @ref="_movementOne">
<div class="rail" aria-hidden="true">
<div class="rail-line"></div>
<div class="rail-numeral">01</div>
<div class="rail-margin">Charleston, SC</div>
</div>
<div class="movement-content">
@* Waveform movement divider — a static SVG oscillation stroke carrying the
movement tag. The folded-in D3 signature motif. *@
<div class="wave-divider">
<svg class="wave-stroke" viewBox="0 0 1200 40" preserveAspectRatio="none" aria-hidden="true">
<path d="@WavePath" />
</svg>
<span class="wave-tag">The People</span>
</div>
@* People intro — prose hangs at the rail's left edge; the sharp line breaks
left into the margin at large serif scale. *@
<div class="movement-intro">
<div class="movement-label">The Collective</div>
<h2 class="movement-title">Two of Us, No Fixed <em>Roles</em></h2>
<p class="movement-prose">
We met trading synthesizers and found out we were seeking the same thing. Two of us, no fixed roles &mdash; we both write, arrange, produce, mix, record in the field, build the visuals, and make the tools when the tools don't exist yet.
</p>
</div>
@* Member bio pair — framed portrait insets with rail-side captions. Each
composes with the body absent (Khabran ships with an empty body slot, the
same null-renders-nothing discipline as ReleaseDescription). *@
<div class="bio-pair">
@foreach (var member in _members)
{
<article class="bio-card">
<div class="bio-portrait">
@if (member.PortraitImage1 is not null)
{
<ParallaxImage Image1="@member.PortraitImage1"
Image2="@member.PortraitImage2"
Alt1="@($"{member.Name} — portrait")"
NaturalWidth="1365"
NaturalHeight="1365"
WindowHeightFraction="1.0"
ImageHeight="auto"
ImageWidth="100%"
ParallaxSpeed="0.3" />
}
else
{
@* Graceful-degrade placeholder until a portrait file lands. *@
<div class="bio-portrait-placeholder" aria-hidden="true"></div>
}
</div>
<div class="bio-caption">@member.Role</div>
<div class="bio-meta">
<div class="bio-name">@member.Name</div>
@if (!string.IsNullOrWhiteSpace(member.Bio))
{
@foreach (var para in member.Bio.Split("\n\n", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
{
<p class="bio-body">@para</p>
}
}
</div>
</article>
}
</div>
</div>
</div>
@* ════════════════ MOVEMENT TWO — THE PROCESS (logos) ════════════════ *@
<div class="movement" data-movement="2" @ref="_movementTwo">
<div class="rail" aria-hidden="true">
<div class="rail-line"></div>
<div class="rail-numeral">02</div>
<div class="rail-margin">the live rig</div>
</div>
<div class="movement-content">
<div class="wave-divider">
<svg class="wave-stroke" viewBox="0 0 1200 40" preserveAspectRatio="none" aria-hidden="true">
<path d="@WavePath" />
</svg>
<span class="wave-tag">The Process</span>
</div>
@* Dark band — gear-stage cards. The navy ground carries the analytical register. *@
<div class="process-band">
<div class="process-label">How It's Made</div>
<h2 class="process-title">Digital, Analog, <em>Whatever Moves</em></h2>
<p class="process-standfirst">
It doesn't matter how &mdash; digital or analog, hard or soft, bought or built &mdash; as long as it moves the room. The soul in this music is designed, not extracted; assembled, not distilled.
</p>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" /><line x1="3" y1="9" x2="21" y2="9" /><line x1="9" y1="9" x2="9" y2="21" /></svg>
</div>
<div class="feature-title">Sketch</div>
<div class="feature-desc">A loop starts on the Force or the MPC, hands on the pads. The idea has to survive first contact before anything else gets built around it.</div>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24"><line x1="4" y1="21" x2="4" y2="14" /><line x1="4" y1="10" x2="4" y2="3" /><line x1="12" y1="21" x2="12" y2="12" /><line x1="12" y1="8" x2="12" y2="3" /><line x1="20" y1="21" x2="20" y2="16" /><line x1="20" y1="12" x2="20" y2="3" /><line x1="1" y1="14" x2="7" y2="14" /><line x1="9" y1="8" x2="15" y2="8" /><line x1="17" y1="16" x2="23" y2="16" /></svg>
</div>
<div class="feature-title">Arrange</div>
<div class="feature-desc">Sometimes into Ableton, sometimes start-to-finish in REAPER. The track gets shaped wherever it wants to go &mdash; we follow the take, not the template.</div>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="3" /><line x1="12" y1="3" x2="12" y2="6" /><line x1="12" y1="18" x2="12" y2="21" /></svg>
</div>
<div class="feature-title">Studio</div>
<div class="feature-desc">A deep bench of synths, drum machines, and pedals; digital and analog, hard and soft, some of it built by hand. If the sound we need doesn't exist yet, we make the thing that makes it.</div>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24"><path d="M3 12h3l2-7 4 14 2-7h3" /><circle cx="20" cy="12" r="1.5" /></svg>
</div>
<div class="feature-title">Live Rig</div>
<div class="feature-desc">No laptop, no safety net. A full spread of hardware patched together and played 100% live &mdash; sequenced, twisted, and pushed in the moment. Built for the room, the warehouse, the night that doesn't repeat.</div>
</div>
</div>
</div>
@* IMG SLOT D — hands-on-gear inset, the literal proof-of-effort image,
captioned in the rail rather than run full-bleed. *@
<figure class="movement-figure">
<ParallaxImage Image1="img/dd-mixer-2-bw.jpeg"
Image2="img/dd-mixer-2.jpg"
Alt1="Deep DRFT — hands on the gear"
NaturalWidth="2048"
NaturalHeight="1365"
WindowHeightFraction="0.45"
ImageHeight="auto"
ImageWidth="100%"
ParallaxSpeed="0.35" />
<figcaption class="figure-caption">the studio rig</figcaption>
</figure>
</div>
</div>
@* ════════════════ MOVEMENT THREE — THE PRODUCT (ethos) ════════════════ *@
<div class="movement" data-movement="3" @ref="_movementThree">
<div class="rail" aria-hidden="true">
<div class="rail-line"></div>
<div class="rail-numeral">03</div>
<div class="rail-margin">in the swamp</div>
</div>
<div class="movement-content">
<div class="wave-divider">
<svg class="wave-stroke" viewBox="0 0 1200 40" preserveAspectRatio="none" aria-hidden="true">
<path d="@WavePath" />
</svg>
<span class="wave-tag">The Product</span>
</div>
<div class="movement-intro">
<div class="movement-label">The Output</div>
<h2 class="movement-title">Classics, with a <em>Twist</em></h2>
<p class="movement-prose">
Everything ends up here, in the catalogue. It's proof people in Charleston are pushing the sound of the club.
</p>
</div>
@* Medium triptych — one-line frame of each medium; definitions, not a re-pitch.
A stacked editorial list rather than Home's card grid. *@
<MudGrid Spacing="16">
<MudItem xs="12" md="6">
<ul class="medium-list">
<li class="medium-row">
<a href="/cuts">
<span class="medium-row-name">Cuts</span>
<span class="medium-row-desc">Studio work, composed and finished.</span>
</a>
</li>
<li class="medium-row">
<a href="/sessions">
<span class="medium-row-name">Sessions</span>
<span class="medium-row-desc">Live, caught once, never the same twice.</span>
</a>
</li>
<li class="medium-row">
<a href="/mixes">
<span class="medium-row-name">Mixes</span>
<span class="medium-row-desc">Uninterrupted sets, start to finish.</span>
</a>
</li>
</ul>
</MudItem>
@* The live turn — "on the street, in the swamp": the identity beyond releases.
A left-breaking pull-quote at large serif scale. *@
<MudItem xs="12" md="6">
<blockquote class="pull-quote">
<span class="pull-eyebrow">Beyond the Releases</span>
<p>
But that's just the releases. We're also out there &mdash; on the street, in the swamp, with a PA, a generator, and a bunch of good vibes.
</p>
</blockquote>
</MudItem>
</MudGrid>
</div>
</div>
@* ── Closing CTA into the catalogue ── *@
<section class="cta-banner">
<div class="cta-text">
<h2 class="cta-headline">Hear the<br /><em>Proof</em></h2>
<p class="cta-sub">The catalogue is the evidence. Start listening.</p>
</div>
<div class="cta-actions">
<a class="btn-white" href="/archive">Explore the Archive</a>
<a class="btn-outline-white" href="/cuts">Hear a Cut</a>
</div>
</section>
@code {
private string AnimClass => RendererInfo.IsInteractive ? string.Empty : "fade-up";
// A static sine path for the movement-divider waveform stroke. Authored as plain
// SVG markup — independent of the live WaveformVisualizer component. The viewBox is
// 1200×40; the curve oscillates around the vertical midline (y=20).
private static readonly string WavePath = BuildWavePath();
private ElementReference _movementOne;
private ElementReference _movementTwo;
private ElementReference _movementThree;
private IJSObjectReference? _railModule;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender || !RendererInfo.IsInteractive)
{
return;
}
try
{
// Progressive enhancement only: lights the active movement's numeral green
// as it scrolls into view. Numerals render statically without this.
_railModule = await JsRuntime.InvokeAsync<IJSObjectReference>(
"import", "./js/about/about-rail.js");
await _railModule.InvokeVoidAsync("observe", _movementOne, _movementTwo, _movementThree);
}
catch (JSException)
{
// Module failed to load — numerals stay statically navy. Nothing actionable.
_railModule = null;
}
}
public async ValueTask DisposeAsync()
{
if (_railModule is not null)
{
try
{
await _railModule.InvokeVoidAsync("unobserve");
await _railModule.DisposeAsync();
}
catch (JSException)
{
// Runtime already gone (navigation/teardown) — nothing to clean up.
}
_railModule = null;
}
}
// Builds an evaluated-at-compile-time sine path string for the divider stroke.
private static string BuildWavePath()
{
// 8 full cycles across the 1200-wide viewBox, amplitude 14 around midline 20.
const int width = 1200;
const int steps = 96;
const double midline = 20;
const double amplitude = 14;
const double cycles = 8;
var sb = new System.Text.StringBuilder("M 0 20");
for (var i = 1; i <= steps; i++)
{
var x = width * (double)i / steps;
var y = midline - amplitude * System.Math.Sin(cycles * 2 * System.Math.PI * i / steps);
sb.Append(System.Globalization.CultureInfo.InvariantCulture, $" L {x:0.##} {y:0.##}");
}
return sb.ToString();
}
private record Member(
string Name,
string Role,
string? Bio,
string? PortraitImage1 = null,
string? PortraitImage2 = null);
private readonly Member[] _members =
[
new(
Name: "Khabran Peters",
Role: "Production · Sound Design · Live",
Bio: "Raised on the Chicago underground, this artist cut his teeth on DJ Assault and DJ Funk. He started DJing young, learning to read a room long before he opened a DAW. After fifteen years as a visual artist, he moved into music production.\n\nNow based in Charleston, his sound carries the city's late-night feel but keeps the kinetic edge of its Midwest roots—deep one minute, fast the next. As much indie sensibility as booty-house grit.\n\nThe work is hardware-first, with software kept to remixes and edits. Onstage he stays out of the way and lets the tracks do the talking. Polished without being precious—built by someone who cares more about the craft than the spotlight.",
PortraitImage1: "img/dd-khabran-bw.jpeg",
PortraitImage2: "img/dd-khabran.jpeg"),
new(
Name: "Daniel Harvey",
Role: "Production · Sound Design · Live",
Bio: "Daniel started on drums at ten and embarked in electronic music at seventeen — synthesizers first. A metalhead from a young age, he spent ten years as an engineer living near Detroit filling the nights with synthesized tones and rhythms, shaped most of all by the thriving local underground techno scene.\n\nNow back home in the lowcountry, Daniel carries the varied sounds of his past into a new future, inspired by the wandering cypress swamps and soulful sunsets over the Ashley River.\n\nArt & engineering cannot be separated: custom plugins, hardware recording & performance rigs; the tools behind the tracks are just as important as the finished sound. To him, the science and the math matter as much as the beauty — tension and release, built deliberately.",
PortraitImage1: "img/dd-daniel-bw.jpeg",
PortraitImage2: "img/dd-daniel.jpeg"),
];
}