mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-23 22:29:59 -07:00
website: snap
This commit is contained in:
@@ -108,15 +108,14 @@ pub fn generate_main_client(
|
||||
writeln!(output, " constructor(options) {{").unwrap();
|
||||
writeln!(output, " super(options);").unwrap();
|
||||
writeln!(output, " /** @type {{SeriesTree}} */").unwrap();
|
||||
writeln!(output, " this.series = this._buildTree('');").unwrap();
|
||||
writeln!(output, " this.series = this._buildTree();").unwrap();
|
||||
writeln!(output, " }}\n").unwrap();
|
||||
|
||||
writeln!(output, " /**").unwrap();
|
||||
writeln!(output, " * @private").unwrap();
|
||||
writeln!(output, " * @param {{string}} basePath").unwrap();
|
||||
writeln!(output, " * @returns {{SeriesTree}}").unwrap();
|
||||
writeln!(output, " */").unwrap();
|
||||
writeln!(output, " _buildTree(basePath) {{").unwrap();
|
||||
writeln!(output, " _buildTree() {{").unwrap();
|
||||
writeln!(output, " return {{").unwrap();
|
||||
let mut generated = BTreeSet::new();
|
||||
generate_tree_initializer(
|
||||
|
||||
@@ -1936,7 +1936,7 @@ impl ActivityOutputsRealizedSupplyUnrealizedPattern2 {
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct BlockChangeCumulativeDeltaSumPattern {
|
||||
pub block: CentsUsdPattern4,
|
||||
pub change_1m: ToPattern2,
|
||||
pub change_1m: ToPattern,
|
||||
pub cumulative: CentsUsdPattern,
|
||||
pub delta: AbsoluteRatePattern2,
|
||||
pub sum: _1m1w1y24hPattern5,
|
||||
@@ -1947,7 +1947,7 @@ impl BlockChangeCumulativeDeltaSumPattern {
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
block: CentsUsdPattern4::new(client.clone(), _m(&acc, "realized_pnl")),
|
||||
change_1m: ToPattern2::new(client.clone(), _m(&acc, "pnl_change_1m_to")),
|
||||
change_1m: ToPattern::new(client.clone(), _m(&acc, "pnl_change_1m_to")),
|
||||
cumulative: CentsUsdPattern::new(client.clone(), _m(&acc, "realized_pnl_cumulative")),
|
||||
delta: AbsoluteRatePattern2::new(client.clone(), _m(&acc, "realized_pnl_delta")),
|
||||
sum: _1m1w1y24hPattern5::new(client.clone(), _m(&acc, "realized_pnl_sum")),
|
||||
@@ -3174,16 +3174,16 @@ impl InPattern2 {
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct InPattern {
|
||||
pub in_loss: ToPattern,
|
||||
pub in_profit: ToPattern,
|
||||
pub in_loss: SharePattern,
|
||||
pub in_profit: SharePattern,
|
||||
}
|
||||
|
||||
impl InPattern {
|
||||
/// Create a new pattern node with accumulated series name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
in_loss: ToPattern::new(client.clone(), _m(&acc, "loss_to_own")),
|
||||
in_profit: ToPattern::new(client.clone(), _m(&acc, "profit_to_own")),
|
||||
in_loss: SharePattern::new(client.clone(), _m(&acc, "loss_share")),
|
||||
in_profit: SharePattern::new(client.clone(), _m(&acc, "profit_share")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3243,12 +3243,12 @@ pub struct SdSmaPattern {
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ToPattern2 {
|
||||
pub struct ToPattern {
|
||||
pub to_mcap: BpsPercentRatioPattern,
|
||||
pub to_rcap: BpsPercentRatioPattern,
|
||||
}
|
||||
|
||||
impl ToPattern2 {
|
||||
impl ToPattern {
|
||||
/// Create a new pattern node with accumulated series name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
@@ -3301,15 +3301,15 @@ impl PricePattern {
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ToPattern {
|
||||
pub to_own: BpsPercentRatioPattern2,
|
||||
pub struct SharePattern {
|
||||
pub share: BpsPercentRatioPattern2,
|
||||
}
|
||||
|
||||
impl ToPattern {
|
||||
impl SharePattern {
|
||||
/// Create a new pattern node with accumulated series name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
to_own: BpsPercentRatioPattern2::new(client.clone(), acc.clone()),
|
||||
share: BpsPercentRatioPattern2::new(client.clone(), acc.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3001,7 +3001,7 @@ function createActivityOutputsRealizedSupplyUnrealizedPattern2(client, acc) {
|
||||
/**
|
||||
* @typedef {Object} BlockChangeCumulativeDeltaSumPattern
|
||||
* @property {CentsUsdPattern4} block
|
||||
* @property {ToPattern2} change1m
|
||||
* @property {ToPattern} change1m
|
||||
* @property {CentsUsdPattern} cumulative
|
||||
* @property {AbsoluteRatePattern2} delta
|
||||
* @property {_1m1w1y24hPattern5} sum
|
||||
@@ -3016,7 +3016,7 @@ function createActivityOutputsRealizedSupplyUnrealizedPattern2(client, acc) {
|
||||
function createBlockChangeCumulativeDeltaSumPattern(client, acc) {
|
||||
return {
|
||||
block: createCentsUsdPattern4(client, _m(acc, 'realized_pnl')),
|
||||
change1m: createToPattern2(client, _m(acc, 'pnl_change_1m_to')),
|
||||
change1m: createToPattern(client, _m(acc, 'pnl_change_1m_to')),
|
||||
cumulative: createCentsUsdPattern(client, _m(acc, 'realized_pnl_cumulative')),
|
||||
delta: createAbsoluteRatePattern2(client, _m(acc, 'realized_pnl_delta')),
|
||||
sum: create_1m1w1y24hPattern5(client, _m(acc, 'realized_pnl_sum')),
|
||||
@@ -4446,8 +4446,8 @@ function createInPattern2(client, acc) {
|
||||
|
||||
/**
|
||||
* @typedef {Object} InPattern
|
||||
* @property {ToPattern} inLoss
|
||||
* @property {ToPattern} inProfit
|
||||
* @property {SharePattern} inLoss
|
||||
* @property {SharePattern} inProfit
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -4458,8 +4458,8 @@ function createInPattern2(client, acc) {
|
||||
*/
|
||||
function createInPattern(client, acc) {
|
||||
return {
|
||||
inLoss: createToPattern(client, _m(acc, 'loss_to_own')),
|
||||
inProfit: createToPattern(client, _m(acc, 'profit_to_own')),
|
||||
inLoss: createSharePattern(client, _m(acc, 'loss_share')),
|
||||
inProfit: createSharePattern(client, _m(acc, 'profit_share')),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4528,18 +4528,18 @@ function createRatioValuePattern(client, acc) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ToPattern2
|
||||
* @typedef {Object} ToPattern
|
||||
* @property {BpsPercentRatioPattern} toMcap
|
||||
* @property {BpsPercentRatioPattern} toRcap
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a ToPattern2 pattern node
|
||||
* Create a ToPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated series name
|
||||
* @returns {ToPattern2}
|
||||
* @returns {ToPattern}
|
||||
*/
|
||||
function createToPattern2(client, acc) {
|
||||
function createToPattern(client, acc) {
|
||||
return {
|
||||
toMcap: createBpsPercentRatioPattern(client, _m(acc, 'mcap')),
|
||||
toRcap: createBpsPercentRatioPattern(client, _m(acc, 'rcap')),
|
||||
@@ -4598,19 +4598,19 @@ function createPricePattern(client, acc) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ToPattern
|
||||
* @property {BpsPercentRatioPattern2} toOwn
|
||||
* @typedef {Object} SharePattern
|
||||
* @property {BpsPercentRatioPattern2} share
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a ToPattern pattern node
|
||||
* Create a SharePattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated series name
|
||||
* @returns {ToPattern}
|
||||
* @returns {SharePattern}
|
||||
*/
|
||||
function createToPattern(client, acc) {
|
||||
function createSharePattern(client, acc) {
|
||||
return {
|
||||
toOwn: createBpsPercentRatioPattern2(client, acc),
|
||||
share: createBpsPercentRatioPattern2(client, acc),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8188,15 +8188,14 @@ class BrkClient extends BrkClientBase {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
/** @type {SeriesTree} */
|
||||
this.series = this._buildTree('');
|
||||
this.series = this._buildTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} basePath
|
||||
* @returns {SeriesTree}
|
||||
*/
|
||||
_buildTree(basePath) {
|
||||
_buildTree() {
|
||||
return {
|
||||
blocks: {
|
||||
blockhash: createSeriesPattern18(this, 'blockhash'),
|
||||
|
||||
@@ -3054,7 +3054,7 @@ class BlockChangeCumulativeDeltaSumPattern:
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.block: CentsUsdPattern4 = CentsUsdPattern4(client, _m(acc, 'realized_pnl'))
|
||||
self.change_1m: ToPattern2 = ToPattern2(client, _m(acc, 'pnl_change_1m_to'))
|
||||
self.change_1m: ToPattern = ToPattern(client, _m(acc, 'pnl_change_1m_to'))
|
||||
self.cumulative: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_pnl_cumulative'))
|
||||
self.delta: AbsoluteRatePattern2 = AbsoluteRatePattern2(client, _m(acc, 'realized_pnl_delta'))
|
||||
self.sum: _1m1w1y24hPattern5 = _1m1w1y24hPattern5(client, _m(acc, 'realized_pnl_sum'))
|
||||
@@ -3672,8 +3672,8 @@ class InPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.in_loss: ToPattern = ToPattern(client, _m(acc, 'loss_to_own'))
|
||||
self.in_profit: ToPattern = ToPattern(client, _m(acc, 'profit_to_own'))
|
||||
self.in_loss: SharePattern = SharePattern(client, _m(acc, 'loss_share'))
|
||||
self.in_profit: SharePattern = SharePattern(client, _m(acc, 'profit_share'))
|
||||
|
||||
class PerPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -3703,7 +3703,7 @@ class SdSmaPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
pass
|
||||
|
||||
class ToPattern2:
|
||||
class ToPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
@@ -3732,12 +3732,12 @@ class PricePattern:
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, acc)
|
||||
|
||||
class ToPattern:
|
||||
class SharePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.to_own: BpsPercentRatioPattern2 = BpsPercentRatioPattern2(client, acc)
|
||||
self.share: BpsPercentRatioPattern2 = BpsPercentRatioPattern2(client, acc)
|
||||
|
||||
class TransferPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -81,13 +81,13 @@
|
||||
* Relative patterns by capability:
|
||||
* Unrealized patterns by capability level
|
||||
* @typedef {Brk.LossNetNuplProfitPattern} BasicRelativePattern
|
||||
* @typedef {Brk.GrossInvestedInvestorLossNetNuplProfitSentimentPattern2} FullRelativePattern
|
||||
* @typedef {Brk.CapitalizedGrossInvestedLossNetNuplProfitSentimentPattern2} FullRelativePattern
|
||||
*
|
||||
* Profitability bucket pattern (supply + realized_cap + unrealized_pnl + nupl)
|
||||
* @typedef {Brk.NuplRealizedSupplyUnrealizedPattern} RealizedSupplyPattern
|
||||
*
|
||||
* Realized pattern (full: cap + gross + capitalized + loss + mvrv + net + peak + price + profit + sell + sopr)
|
||||
* @typedef {Brk.CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern} RealizedPattern
|
||||
* @typedef {Brk.CapCapitalizedGrossLossMvrvNetPeakPriceProfitSellSoprPattern} RealizedPattern
|
||||
*
|
||||
* Transfer volume pattern (block + cumulative + inProfit/inLoss + sum windows)
|
||||
* @typedef {Brk.AverageBlockCumulativeInSumPattern} TransferVolumePattern
|
||||
@@ -242,19 +242,6 @@
|
||||
* @typedef {CohortFull | CohortLongTerm} CohortWithNuplPercentiles
|
||||
* @typedef {{ name: string, title: string, list: readonly CohortWithNuplPercentiles[], all: CohortAll }} CohortGroupWithNuplPercentiles
|
||||
*
|
||||
* Cohorts with RealizedWithExtras (realizedCapRelToOwnMarketCap + realizedProfitToLossRatio)
|
||||
* @typedef {CohortAll | CohortFull | CohortWithPercentiles} CohortWithRealizedExtras
|
||||
*
|
||||
* Cohorts with circulating supply relative series (supplyRelToCirculatingSupply etc.)
|
||||
* These have GlobalRelativePattern or FullRelativePattern (same as RelativeWithMarketCap/RelativeWithNupl)
|
||||
* @typedef {CohortFull | CohortLongTerm | CohortWithAdjusted | CohortBasicWithMarketCap} UtxoCohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* Address cohorts with circulating supply relative series (all address amount cohorts have these)
|
||||
* @typedef {AddrCohortObject} AddrCohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* All cohorts with circulating supply relative series
|
||||
* @typedef {UtxoCohortWithCirculatingSupplyRelative | AddrCohortWithCirculatingSupplyRelative} CohortWithCirculatingSupplyRelative
|
||||
*
|
||||
* Delta patterns with absolute + rate rolling windows
|
||||
* @typedef {Brk.AbsoluteRatePattern} DeltaPattern
|
||||
* @typedef {Brk.AbsoluteRatePattern2} FiatDeltaPattern
|
||||
|
||||
@@ -38,6 +38,7 @@ export function initChain(parent, callbacks) {
|
||||
|
||||
olderObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
return; // edge fetching disabled for layout debugging
|
||||
if (entries[0].isIntersecting) loadOlder();
|
||||
},
|
||||
{ root: chainEl },
|
||||
@@ -46,6 +47,7 @@ export function initChain(parent, callbacks) {
|
||||
chainEl.addEventListener(
|
||||
"scroll",
|
||||
() => {
|
||||
return; // edge fetching disabled for layout debugging
|
||||
const nearStart =
|
||||
(chainEl.scrollHeight > chainEl.clientHeight &&
|
||||
chainEl.scrollTop <= 50) ||
|
||||
|
||||
@@ -38,32 +38,37 @@ export function createCointimeSection() {
|
||||
},
|
||||
]);
|
||||
|
||||
const prices = /** @type {const} */ ([
|
||||
/** @type {readonly { pattern: PriceRatioPercentilesPattern, name: string, title: (name: string) => string, color: Color, defaultActive: boolean }[]} */
|
||||
const prices = [
|
||||
{
|
||||
pattern: cointimePrices.trueMarketMean,
|
||||
name: "True Market Mean",
|
||||
title: (name) => name,
|
||||
color: colors.trueMarketMean,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.vaulted,
|
||||
name: "Vaulted",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.vaulted,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.active,
|
||||
name: "Active",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.active,
|
||||
defaultActive: true,
|
||||
},
|
||||
{
|
||||
pattern: cointimePrices.cointime,
|
||||
name: "Cointime",
|
||||
title: (name) => `${name} Price`,
|
||||
color: colors.cointime,
|
||||
defaultActive: true,
|
||||
},
|
||||
]);
|
||||
];
|
||||
|
||||
const caps = /** @type {const} */ ([
|
||||
{
|
||||
@@ -187,11 +192,11 @@ export function createCointimeSection() {
|
||||
),
|
||||
],
|
||||
},
|
||||
...prices.map(({ pattern, name, color }) => ({
|
||||
...prices.map(({ pattern, name, title, color }) => ({
|
||||
name,
|
||||
tree: priceRatioPercentilesTree({
|
||||
pattern,
|
||||
title: `${name} Price`,
|
||||
title: title(name),
|
||||
legend: name,
|
||||
color,
|
||||
priceReferences: [
|
||||
|
||||
@@ -254,9 +254,6 @@ export function createSelect({
|
||||
? unsortedChoices.toSorted((a, b) => toLabel(a).localeCompare(toLabel(b)))
|
||||
: unsortedChoices;
|
||||
|
||||
const field = window.document.createElement("div");
|
||||
field.classList.add("field");
|
||||
|
||||
const initialKey = toKey(initialValue);
|
||||
|
||||
/** @param {string} key */
|
||||
@@ -266,56 +263,59 @@ export function createSelect({
|
||||
if (choices.length === 1) {
|
||||
const span = window.document.createElement("span");
|
||||
span.textContent = toLabel(choices[0]);
|
||||
field.append(span);
|
||||
} else {
|
||||
const select = window.document.createElement("select");
|
||||
select.id = id ?? "";
|
||||
select.name = id ?? "";
|
||||
field.append(select);
|
||||
|
||||
/** @param {T} choice */
|
||||
const createOption = (choice) => {
|
||||
const option = window.document.createElement("option");
|
||||
option.value = toKey(choice);
|
||||
option.textContent = toLabel(choice);
|
||||
if (toKey(choice) === initialKey) {
|
||||
option.selected = true;
|
||||
}
|
||||
return option;
|
||||
};
|
||||
|
||||
if (groups) {
|
||||
groups.forEach(({ label, items }) => {
|
||||
const optgroup = window.document.createElement("optgroup");
|
||||
optgroup.label = label;
|
||||
items.forEach((choice) => optgroup.append(createOption(choice)));
|
||||
select.append(optgroup);
|
||||
});
|
||||
} else {
|
||||
choices.forEach((choice) => select.append(createOption(choice)));
|
||||
}
|
||||
|
||||
select.addEventListener("change", () => {
|
||||
onChange?.(fromKey(select.value));
|
||||
});
|
||||
|
||||
const remaining = choices.length - 1;
|
||||
if (remaining > 0) {
|
||||
const small = window.document.createElement("small");
|
||||
small.textContent = `+${remaining}`;
|
||||
field.append(small);
|
||||
const arrow = window.document.createElement("span");
|
||||
arrow.textContent = "↓";
|
||||
field.append(arrow);
|
||||
}
|
||||
|
||||
field.addEventListener("click", (e) => {
|
||||
if (e.target !== select) {
|
||||
select.showPicker();
|
||||
}
|
||||
});
|
||||
return span;
|
||||
}
|
||||
|
||||
const field = window.document.createElement("div");
|
||||
field.classList.add("field");
|
||||
|
||||
const select = window.document.createElement("select");
|
||||
select.id = id ?? "";
|
||||
select.name = id ?? "";
|
||||
field.append(select);
|
||||
|
||||
/** @param {T} choice */
|
||||
const createOption = (choice) => {
|
||||
const option = window.document.createElement("option");
|
||||
option.value = toKey(choice);
|
||||
option.textContent = toLabel(choice);
|
||||
if (toKey(choice) === initialKey) {
|
||||
option.selected = true;
|
||||
}
|
||||
return option;
|
||||
};
|
||||
|
||||
if (groups) {
|
||||
groups.forEach(({ label, items }) => {
|
||||
const optgroup = window.document.createElement("optgroup");
|
||||
optgroup.label = label;
|
||||
items.forEach((choice) => optgroup.append(createOption(choice)));
|
||||
select.append(optgroup);
|
||||
});
|
||||
} else {
|
||||
choices.forEach((choice) => select.append(createOption(choice)));
|
||||
}
|
||||
|
||||
select.addEventListener("change", () => {
|
||||
onChange?.(fromKey(select.value));
|
||||
});
|
||||
|
||||
const remaining = choices.length - 1;
|
||||
if (remaining > 0) {
|
||||
const small = window.document.createElement("small");
|
||||
small.textContent = `+${remaining}`;
|
||||
field.append(small);
|
||||
const arrow = window.document.createElement("span");
|
||||
arrow.textContent = "↓";
|
||||
field.append(arrow);
|
||||
}
|
||||
|
||||
field.addEventListener("click", (e) => {
|
||||
if (e.target !== select) {
|
||||
select.showPicker();
|
||||
}
|
||||
});
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
> span {
|
||||
> *:nth-child(2) {
|
||||
color: var(--gray);
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
> label {
|
||||
> span {
|
||||
display: flex !important;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&:has(input:not(:checked)) {
|
||||
@@ -115,11 +115,11 @@
|
||||
|
||||
&:hover {
|
||||
* {
|
||||
color: var(--off-color) !important;
|
||||
color: var(--off-color);
|
||||
}
|
||||
|
||||
> span.main > span.name {
|
||||
text-decoration-color: var(--orange) !important;
|
||||
text-decoration-color: var(--orange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,18 +30,28 @@ a {
|
||||
text-decoration-color: inherit;
|
||||
}
|
||||
|
||||
&[target="_blank"]::after {
|
||||
color: var(--off-color);
|
||||
content: "↗";
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
&[target="_blank"] {
|
||||
&::after {
|
||||
color: var(--off-color);
|
||||
content: "↗";
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
|
||||
margin-top: 0.1rem;
|
||||
margin-left: 0.375rem;
|
||||
line-height: 1;
|
||||
margin-top: 0.1rem;
|
||||
margin-left: 0.375rem;
|
||||
line-height: 1;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
&:active::after {
|
||||
color: var(--orange);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +65,8 @@ aside {
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
background: var(--background-color);
|
||||
container-type: inline-size;
|
||||
container-name: aside;
|
||||
|
||||
html[data-layout="split"] & {
|
||||
grid-column: 2;
|
||||
@@ -208,11 +220,6 @@ select {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
summary > small {
|
||||
margin-left: 0.375rem;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
small {
|
||||
color: var(--off-color);
|
||||
font-weight: var(--font-weight-base);
|
||||
@@ -249,28 +256,33 @@ summary {
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> small {
|
||||
margin-left: 0.375rem;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&:hover > small {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
&:active > small {
|
||||
color: var(--orange);
|
||||
}
|
||||
}
|
||||
|
||||
:is(a, button, summary) {
|
||||
&:hover {
|
||||
&,
|
||||
*,
|
||||
&::after {
|
||||
color: var(--color);
|
||||
}
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
&:active {
|
||||
&,
|
||||
*,
|
||||
&::after {
|
||||
color: var(--orange);
|
||||
}
|
||||
color: var(--orange);
|
||||
}
|
||||
}
|
||||
|
||||
html[data-layout="split"] .full-only {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#layout-button {
|
||||
|
||||
@@ -36,7 +36,7 @@ main {
|
||||
}
|
||||
|
||||
html[data-layout="full"] & {
|
||||
width: 100% !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
html[data-layout="split"] & {
|
||||
|
||||
@@ -61,7 +61,6 @@ li[data-highlight] {
|
||||
|
||||
> a::after,
|
||||
> details:not([open]) > summary::after {
|
||||
color: var(--orange) !important;
|
||||
content: "";
|
||||
background-color: var(--orange);
|
||||
width: 0.375rem;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
@container aside (max-width: 767px) {
|
||||
overflow-y: auto;
|
||||
padding: var(--main-padding) 0;
|
||||
flex-direction: column;
|
||||
@@ -23,25 +23,58 @@
|
||||
known source of jank there. Each interaction state gets its own
|
||||
set; the .cube rule below just swaps which set --face-right /
|
||||
--face-left / --face-top / --face-bottom reference. */
|
||||
--cube-neutral-right: light-dark(oklch(from var(--light-gray) calc(l - var(--face-step) * 2) c h), var(--dark-gray));
|
||||
--cube-neutral-left: light-dark(oklch(from var(--light-gray) calc(l - var(--face-step)) c h), oklch(from var(--dark-gray) calc(l + var(--face-step)) c h));
|
||||
--cube-neutral-top: light-dark(var(--light-gray), oklch(from var(--dark-gray) calc(l + var(--face-step) * 2) c h));
|
||||
--cube-neutral-bottom: oklch(from var(--border-color) calc(l - var(--face-step) * 3) c h);
|
||||
--cube-neutral-right: light-dark(
|
||||
oklch(from var(--light-gray) calc(l - var(--face-step) * 2) c h),
|
||||
var(--dark-gray)
|
||||
);
|
||||
--cube-neutral-left: light-dark(
|
||||
oklch(from var(--light-gray) calc(l - var(--face-step)) c h),
|
||||
oklch(from var(--dark-gray) calc(l + var(--face-step)) c h)
|
||||
);
|
||||
--cube-neutral-top: light-dark(
|
||||
var(--light-gray),
|
||||
oklch(from var(--dark-gray) calc(l + var(--face-step) * 2) c h)
|
||||
);
|
||||
--cube-neutral-bottom: oklch(
|
||||
from var(--border-color) calc(l - var(--face-step) * 3) c h
|
||||
);
|
||||
|
||||
--cube-hover-right: light-dark(oklch(from var(--dark-gray) calc(l - var(--face-step) * 2) c h), var(--light-gray));
|
||||
--cube-hover-left: light-dark(oklch(from var(--dark-gray) calc(l - var(--face-step)) c h), oklch(from var(--light-gray) calc(l + var(--face-step)) c h));
|
||||
--cube-hover-top: light-dark(var(--dark-gray), oklch(from var(--light-gray) calc(l + var(--face-step) * 2) c h));
|
||||
--cube-hover-bottom: oklch(from var(--inv-border-color) calc(l - var(--face-step) * 3) c h);
|
||||
--cube-hover-right: light-dark(
|
||||
oklch(from var(--dark-gray) calc(l - var(--face-step) * 2) c h),
|
||||
var(--light-gray)
|
||||
);
|
||||
--cube-hover-left: light-dark(
|
||||
oklch(from var(--dark-gray) calc(l - var(--face-step)) c h),
|
||||
oklch(from var(--light-gray) calc(l + var(--face-step)) c h)
|
||||
);
|
||||
--cube-hover-top: light-dark(
|
||||
var(--dark-gray),
|
||||
oklch(from var(--light-gray) calc(l + var(--face-step) * 2) c h)
|
||||
);
|
||||
--cube-hover-bottom: oklch(
|
||||
from var(--inv-border-color) calc(l - var(--face-step) * 3) c h
|
||||
);
|
||||
|
||||
--cube-selected-right: light-dark(oklch(from var(--orange) calc(l - var(--face-step) * 2) c h), var(--orange));
|
||||
--cube-selected-left: light-dark(oklch(from var(--orange) calc(l - var(--face-step)) c h), oklch(from var(--orange) calc(l + var(--face-step)) c h));
|
||||
--cube-selected-top: light-dark(var(--orange), oklch(from var(--orange) calc(l + var(--face-step) * 2) c h));
|
||||
--cube-selected-bottom: oklch(from var(--orange) calc(l - var(--face-step) * 3) c h);
|
||||
--cube-selected-right: light-dark(
|
||||
oklch(from var(--orange) calc(l - var(--face-step) * 2) c h),
|
||||
var(--orange)
|
||||
);
|
||||
--cube-selected-left: light-dark(
|
||||
oklch(from var(--orange) calc(l - var(--face-step)) c h),
|
||||
oklch(from var(--orange) calc(l + var(--face-step)) c h)
|
||||
);
|
||||
--cube-selected-top: light-dark(
|
||||
var(--orange),
|
||||
oklch(from var(--orange) calc(l + var(--face-step) * 2) c h)
|
||||
);
|
||||
--cube-selected-bottom: oklch(
|
||||
from var(--orange) calc(l - var(--face-step) * 3) c h
|
||||
);
|
||||
|
||||
> * {
|
||||
padding: 0 var(--main-padding);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@container aside (min-width: 768px) {
|
||||
padding: var(--main-padding);
|
||||
}
|
||||
}
|
||||
@@ -49,11 +82,11 @@
|
||||
#chain {
|
||||
flex-shrink: 0;
|
||||
|
||||
@media (max-width: 767px) {
|
||||
@container aside (max-width: 767px) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@container aside (min-width: 768px) {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
padding-right: calc(var(--main-padding) / 2);
|
||||
@@ -67,16 +100,16 @@
|
||||
--min-dt: 0;
|
||||
--max-dt: 10800;
|
||||
margin-right: var(--cube);
|
||||
margin-top: calc(var(--cube) * -0.25);
|
||||
|
||||
@media (max-width: 767px) {
|
||||
--max-gap: calc(var(--cube) * 1.5);
|
||||
@container aside (max-width: 767px) {
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
height: 11.5rem;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@container aside (min-width: 768px) {
|
||||
margin-top: calc(var(--cube) * -0.25);
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
}
|
||||
@@ -103,9 +136,9 @@
|
||||
/* Face colors reference the precomputed sets on #explorer
|
||||
(see top of file). Hover / selected rules just switch which
|
||||
set each --face-* points at. */
|
||||
--face-right: var(--cube-neutral-right);
|
||||
--face-left: var(--cube-neutral-left);
|
||||
--face-top: var(--cube-neutral-top);
|
||||
--face-right: var(--cube-neutral-right);
|
||||
--face-left: var(--cube-neutral-left);
|
||||
--face-top: var(--cube-neutral-top);
|
||||
--face-bottom: var(--cube-neutral-bottom);
|
||||
|
||||
/* Fill-driven state. --liquid-y is the liquid's vertical scale;
|
||||
@@ -136,25 +169,27 @@
|
||||
|
||||
&:hover {
|
||||
color: var(--background-color);
|
||||
--face-right: var(--cube-hover-right);
|
||||
--face-left: var(--cube-hover-left);
|
||||
--face-top: var(--cube-hover-top);
|
||||
--face-right: var(--cube-hover-right);
|
||||
--face-left: var(--cube-hover-left);
|
||||
--face-top: var(--cube-hover-top);
|
||||
--face-bottom: var(--cube-hover-bottom);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.selected {
|
||||
color: var(--black);
|
||||
--face-right: var(--cube-selected-right);
|
||||
--face-left: var(--cube-selected-left);
|
||||
--face-top: var(--cube-selected-top);
|
||||
--face-right: var(--cube-selected-right);
|
||||
--face-left: var(--cube-selected-left);
|
||||
--face-top: var(--cube-selected-top);
|
||||
--face-bottom: var(--cube-selected-bottom);
|
||||
}
|
||||
|
||||
/* Skeleton state (cube painted but data is stale while a new
|
||||
chunk loads): hide text AND the pool logo. Using visibility
|
||||
rather than color:transparent so the raw <img> logo hides too. */
|
||||
&.skeleton .face-text { visibility: hidden; }
|
||||
&.skeleton .face-text {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Shared face-transform template. Each face div sets --orient,
|
||||
--x, --y, --sx, --sy and its role (liquid/glass/face-text)
|
||||
@@ -181,7 +216,8 @@
|
||||
will-change is on the painted roles only (not .face-text,
|
||||
whose background never changes) so each liquid/glass gets its
|
||||
own compositor layer for snappy hover/select repaints. */
|
||||
.liquid, .glass {
|
||||
.liquid,
|
||||
.glass {
|
||||
will-change: background-color;
|
||||
transition: background-color var(--state-ease);
|
||||
}
|
||||
@@ -196,7 +232,9 @@
|
||||
--sy: var(--glass-y);
|
||||
--y-offset: 0;
|
||||
}
|
||||
.glass.top { opacity: calc(1 - var(--is-full)); }
|
||||
.glass.top {
|
||||
opacity: calc(1 - var(--is-full));
|
||||
}
|
||||
|
||||
.face-text {
|
||||
--sy: var(--iso-scale);
|
||||
@@ -214,9 +252,16 @@
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.face-text.top { justify-content: center; text-transform: uppercase; }
|
||||
.face-text.right { justify-content: space-between; }
|
||||
.face-text p { margin: 0; }
|
||||
.face-text.top {
|
||||
justify-content: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.face-text.right {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.face-text p {
|
||||
margin: 0;
|
||||
}
|
||||
.face-text .height {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: normal;
|
||||
@@ -254,12 +299,19 @@
|
||||
their rear twins share the side-face orients). --sy is only
|
||||
shared on the top/bottom pair (always full iso rhombus);
|
||||
side faces inherit --sy from their role (liquid/glass/face-text). */
|
||||
.top, .bottom {
|
||||
.top,
|
||||
.bottom {
|
||||
--orient: rotate(30deg) skewX(-30deg);
|
||||
--sy: var(--iso-scale);
|
||||
}
|
||||
.right, .rear-left { --orient: rotate(-30deg) skewX(-30deg); }
|
||||
.left, .rear-right { --orient: rotate(30deg) skewX(30deg); }
|
||||
.right,
|
||||
.rear-left {
|
||||
--orient: rotate(-30deg) skewX(-30deg);
|
||||
}
|
||||
.left,
|
||||
.rear-right {
|
||||
--orient: rotate(30deg) skewX(30deg);
|
||||
}
|
||||
|
||||
.bottom {
|
||||
--fc: var(--face-bottom);
|
||||
@@ -268,14 +320,20 @@
|
||||
}
|
||||
.top {
|
||||
--fc: var(--face-top);
|
||||
--x: calc(var(--ox) + var(--top-x-shift, 0) + var(--oy) / var(--iso-scale));
|
||||
--x: calc(
|
||||
var(--ox) + var(--top-x-shift, 0) + var(--oy) / var(--iso-scale)
|
||||
);
|
||||
--y: calc(var(--oy) - var(--iso-scale) + var(--y-offset));
|
||||
}
|
||||
.liquid.top { --top-x-shift: calc(1 - var(--fill)); }
|
||||
.liquid.top {
|
||||
--top-x-shift: calc(1 - var(--fill));
|
||||
}
|
||||
.right {
|
||||
--fc: var(--face-right);
|
||||
--x: calc(var(--ox) + 1);
|
||||
--y: calc((var(--ox) + 1) * var(--iso-scale) + var(--oy) + var(--y-offset));
|
||||
--y: calc(
|
||||
(var(--ox) + 1) * var(--iso-scale) + var(--oy) + var(--y-offset)
|
||||
);
|
||||
}
|
||||
.left {
|
||||
--fc: var(--face-left);
|
||||
@@ -308,7 +366,7 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
@container aside (max-width: 767px) {
|
||||
margin-bottom: 0;
|
||||
margin-right: var(--block-gap);
|
||||
|
||||
@@ -332,7 +390,7 @@
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: var(--line-height-sm);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@container aside (min-width: 768px) {
|
||||
overflow-y: auto;
|
||||
padding-left: calc(var(--main-padding) / 2);
|
||||
}
|
||||
@@ -342,7 +400,7 @@
|
||||
|
||||
code {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 300 !important;
|
||||
font-weight: 300;
|
||||
font-family: Lilex;
|
||||
color: var(--off-color);
|
||||
letter-spacing: -0.05rem;
|
||||
|
||||
Reference in New Issue
Block a user