From 3e932b4f3396e250c48b8ff7834a1fa50edbc231 Mon Sep 17 00:00:00 2001 From: iAmKeralis1131f Date: Tue, 24 Mar 2026 23:45:31 +0530 Subject: [PATCH] bug fixes --- CLAUDE.md | 60 +++- api1.js | 53 +++- src/components/swap/Coinswap.js | 21 +- src/components/swap/SwapHistory.js | 392 +++++++++++++++--------- src/components/swap/SwapReport.js | 46 ++- src/components/swap/SwapStateManager.js | 18 ++ src/styles/output.css | 88 +----- 7 files changed, 432 insertions(+), 246 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 9d36a35..d19813b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,4 +225,62 @@ When reviewing code, pay special attention to: --- -**For Reviewers**: This is a privacy-focused Bitcoin application. Security and correctness are paramount. When in doubt about Bitcoin/Lightning/swap mechanics, ask for clarification rather than making assumptions. \ No newline at end of file +**For Reviewers**: This is a privacy-focused Bitcoin application. Security and correctness are paramount. When in doubt about Bitcoin/Lightning/swap mechanics, ask for clarification rather than making assumptions. + + +## Orchestration Protocol + +When given a task, always follow this pipeline. Do not skip steps. + +### Step 1 — Plan first, code never first + +Before touching any file, produce a planning doc in this format: +``` +## Task: + +### Affected files +- `src/api/makers.rs` — reason +- `frontend/app/routes/makers.tsx` — reason + +### Agent assignments +- Agent 1: [file list] — [what it does] +- Agent 2: [file list] — [what it does] + +### Complexity: small | medium | large +### Agent count: 1 | 2 | 5 +``` + +Rules for agent count: +- **1 agent** — single file, or changes are tightly coupled across files +- **2 agents** — 2-4 files, clearly separable (e.g. backend + frontend split) +- **5 agents** — 5+ files, each agent owns a distinct module/domain + +### Step 2 — Spawn agents via Task tool + +Each Task agent receives: +- Its assigned files only (no awareness of other agents' files) +- The specific goal for its slice +- The relevant architecture context from this CLAUDE.md + +**Hard rule: no two agents may touch the same file. If a file needs changes from two concerns, one agent owns it and handles both.** + +### Step 3 — Review + +After all agents complete, spawn 1-2 review Tasks that: +- Read all changed files together +- Check for: type mismatches across the API boundary, broken imports, inconsistent naming, logic errors +- If issues found: report back to planner, re-assign fixes to the relevant agent +- If clean: proceed + +### Step 4 — Cleanup + +Run the appropriate formatters based on what changed: +- Any `.rs` files touched → `cargo fmt` +- Any `.ts` / `.tsx` files touched → `cd frontend && npx prettier --write ` +- If both → run both + +### Step 5 — Verify + +- If `.rs` changed → `cargo build` (not release, just check it compiles) +- If `.ts`/`.tsx` changed → `cd frontend && npm run build` +- Report any errors back to planner for a fix cycle \ No newline at end of file diff --git a/api1.js b/api1.js index e4790c4..ca6a979 100644 --- a/api1.js +++ b/api1.js @@ -33,6 +33,28 @@ const api1State = { // HELPER FUNCTIONS // ============================================================================ +/** + * Returns true if a maker from the offerbook is usable for a swap. + * Mirrors the categorization logic in the offerbook handler. + */ +function isUsableMaker(maker) { + const state = maker.state; + const normalizedState = + typeof state === 'string' + ? state.toLowerCase() + : state && typeof state === 'object' + ? Object.keys(state)[0]?.toLowerCase() + : null; + if (normalizedState === 'unresponsive' || normalizedState === 'bad') { + return false; + } + if (normalizedState === 'good') { + return true; + } + // Fallback for older payloads without an explicit state. + return maker.offer != null; +} + function getCurrentWalletName() { try { const configPath = path.join(api1State.DATA_DIR, 'config.toml'); @@ -908,16 +930,23 @@ function registerTakerHandlers() { makers.forEach((maker) => { const state = maker.state; - - if (state && state.Unresponsive) { + const normalizedState = + typeof state === 'string' + ? state.toLowerCase() + : state && typeof state === 'object' + ? Object.keys(state)[0]?.toLowerCase() + : null; + + if (normalizedState === 'unresponsive') { unresponsiveMakers.push(maker); - } else if (state && state.Bad) { + } else if (normalizedState === 'bad') { badMakers.push(maker); - } else if (maker.offer !== null) { - // Good makers have offers + } else if (normalizedState === 'good') { + goodMakers.push(maker); + } else if (maker.offer != null) { + // Fallback for older payloads without an explicit state. goodMakers.push(maker); } else { - // Fallback: makers without offers go to unresponsive unresponsiveMakers.push(maker); } }); @@ -1034,11 +1063,7 @@ function registerCoinswapHandlers() { const offerbookData = fs.readFileSync(offerbookPath, 'utf8'); const offerbook = JSON.parse(offerbookData); const makers = offerbook.makers || []; - const goodMakersCount = makers.filter( - (m) => - m.offer !== null && - !(m.state && (m.state.Unresponsive || m.state.Bad)) - ).length; + const goodMakersCount = makers.filter(isUsableMaker).length; if (goodMakersCount >= makerCount) { console.log( @@ -1069,11 +1094,7 @@ function registerCoinswapHandlers() { const offerbookData = fs.readFileSync(offerbookPath, 'utf8'); const offerbook = JSON.parse(offerbookData); const makers = offerbook.makers || []; - const goodMakersCount = makers.filter( - (m) => - m.offer !== null && - !(m.state && (m.state.Unresponsive || m.state.Bad)) - ).length; + const goodMakersCount = makers.filter(isUsableMaker).length; if (goodMakersCount < makerCount) { console.error( diff --git a/src/components/swap/Coinswap.js b/src/components/swap/Coinswap.js index 928b3b8..4d67a57 100644 --- a/src/components/swap/Coinswap.js +++ b/src/components/swap/Coinswap.js @@ -723,7 +723,12 @@ export async function CoinswapComponent(container, swapConfig) { 'fundingTxidsByHop', [] ); - const totalFee = getValue('total_fee', 'totalFee', 0); + const feePaidOrEarned = getValue( + 'fee_paid_or_earned', + 'feePaidOrEarned', + NaN + ); + const totalFee = getValue('total_fee', 'totalFee', NaN); const miningFee = getValue('mining_fee', 'miningFee', 0); const inputUtxos = getArrayValue('input_utxos', 'inputUtxos', []); const outputRegularUtxos = getArrayValue( @@ -769,9 +774,17 @@ export async function CoinswapComponent(container, swapConfig) { }; }); - const calculatedMiningFee = miningFee || totalFee - totalMakerFees; + const derivedTotalFee = Number.isFinite(feePaidOrEarned) + ? Math.abs(feePaidOrEarned) + : totalMakerFees + miningFee; + const normalizedTotalFee = + Number.isFinite(totalFee) && (totalFee > 0 || derivedTotalFee <= 0) + ? totalFee + : derivedTotalFee; + const calculatedMiningFee = + miningFee || normalizedTotalFee - totalMakerFees; const feePercentage = - targetAmount > 0 ? (totalFee / targetAmount) * 100 : 0; + targetAmount > 0 ? (normalizedTotalFee / targetAmount) * 100 : 0; return { swapId, @@ -783,7 +796,7 @@ export async function CoinswapComponent(container, swapConfig) { makerAddresses, totalFundingTxs, fundingTxidsByHop, - totalFee, + totalFee: normalizedTotalFee, totalMakerFees, miningFee: calculatedMiningFee, feePercentage, diff --git a/src/components/swap/SwapHistory.js b/src/components/swap/SwapHistory.js index 787c34e..d192138 100644 --- a/src/components/swap/SwapHistory.js +++ b/src/components/swap/SwapHistory.js @@ -1,9 +1,10 @@ -import { formatRelativeTime } from './SwapStateManager.js'; +import { + SwapStateManager, + formatRelativeTime, + formatElapsedTime, +} from './SwapStateManager.js'; -function satsToBtc(sats) { - if (typeof sats !== 'number' || isNaN(sats)) return '0.00000000'; - return (sats / 100000000).toFixed(8); -} +let swapHistory = []; function formatDuration(seconds) { if (typeof seconds !== 'number' || isNaN(seconds)) return '0m 0s'; @@ -36,15 +37,49 @@ function getProtocolBadgeClasses(protocolLabel) { function normalizeSwapReport(report) { const nested = report.report || {}; + const toNumber = (value, fallback = 0) => { + const normalized = Number(value); + return Number.isFinite(normalized) ? normalized : fallback; + }; const startedAt = report.startedAt || nested.startedAt || Date.now(); const completedAt = report.completedAt || report.failedAt || nested.completedAt || Date.now(); + const totalMakerFees = toNumber( + nested.totalMakerFees ?? + nested.total_maker_fees ?? + report.totalMakerFees ?? + report.total_maker_fees, + 0 + ); + const miningFee = toNumber( + nested.miningFee ?? + nested.mining_fee ?? + report.miningFee ?? + report.mining_fee, + 0 + ); + const feePaidOrEarned = toNumber( + nested.fee_paid_or_earned ?? + nested.feePaidOrEarned ?? + report.fee_paid_or_earned ?? + report.feePaidOrEarned, + NaN + ); + const providedTotalFee = toNumber( + nested.totalFee ?? + nested.total_fee ?? + report.totalFee ?? + report.total_fee, + NaN + ); + const derivedTotalFee = Number.isFinite(feePaidOrEarned) + ? Math.abs(feePaidOrEarned) + : totalMakerFees + miningFee; const totalFee = - nested.totalFee || - nested.total_fee || - report.totalFee || - report.total_fee || - 0; + Number.isFinite(providedTotalFee) && + (providedTotalFee > 0 || derivedTotalFee <= 0) + ? providedTotalFee + : derivedTotalFee; const makersCount = nested.makersCount || nested.makers_count || report.makerCount || 0; @@ -72,113 +107,196 @@ function normalizeSwapReport(report) { export async function loadSwapHistory() { try { const result = await window.api.swapReports.getAll(); - if (!result.success) { - throw new Error(result.error || 'Failed to load swap history'); + if (result.success && result.reports) { + swapHistory = result.reports + .filter((report) => report.status === 'completed') // ✅ Only show completed + .map((report) => { + const normalized = normalizeSwapReport(report); + return { + id: normalized.id, + completedAt: normalized.completedAt, + amount: normalized.amount, + totalOutputAmount: normalized.totalOutputAmount, + makersCount: normalized.makersCount, + hops: normalized.hops, + totalFee: normalized.totalFee, + feePercentage: normalized.feePercentage, + durationSeconds: normalized.durationSeconds, + status: normalized.status, + report: normalized.report, + }; + }); } - return (result.reports || []).map(normalizeSwapReport); } catch (error) { console.error('Failed to load swap history:', error); - throw error; } } -export function summarizeSwapHistory(swapHistory) { - const totalSwaps = swapHistory.length; - const totalAmount = swapHistory.reduce((sum, s) => sum + (s.amount || 0), 0); - const totalFees = swapHistory.reduce((sum, s) => sum + (s.totalFee || 0), 0); - const avgFeePaid = - totalSwaps > 0 ? Math.round(totalFees / totalSwaps) : 0; +export async function SwapHistoryComponent(container) { + if (container.querySelector('#swap-history-content')) { + console.log('⚠️ SwapHistory component already rendered, skipping'); + return; + } - return { - totalSwaps, - totalAmount, - totalFees, - avgFeePaid, - }; -} + console.log('📜 SwapHistoryComponent loading...'); + await loadSwapHistory(); -export function buildSwapHistoryMarkup(swapHistory) { - if (swapHistory.length === 0) { - return ` -
-
🔄
-

No Swap History

-

Your completed and failed swaps will appear here.

-
- `; + const content = document.createElement('div'); + content.id = 'swap-history-content'; + + function satsToBtc(sats) { + if (typeof sats !== 'number' || isNaN(sats)) return '0.00000000'; + return (sats / 100000000).toFixed(8); } - return ` -
-
-
Swap
-
Status
-
Protocol
-
Amount
-
Fee Paid
-
When
-
-
+ function formatDuration(seconds) { + if (typeof seconds !== 'number' || isNaN(seconds)) return '0m 0s'; + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}m ${secs}s`; + } + + function formatDate(timestamp) { + const date = new Date(timestamp); + return date.toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + } + + async function viewSwapReport(swapId) { + try { + const result = await window.api.swapReports.get(swapId); + console.log('📋 Raw result from API:', result); // ← ADD THIS + console.log('📋 Report from result:', result.report.report); // ← ADD THIS + + if (result.success && result.report) { + import('./SwapReport.js').then((module) => { + container.innerHTML = ''; + const fullReport = { + ...result.report.report, + protocol: result.report.protocol ?? 'v1', + isTaproot: result.report.isTaproot ?? false, + protocolVersion: result.report.protocolVersion ?? 1, + }; + module.SwapReportComponent(container, fullReport); + }); + } else { + console.error('Swap report not found for ID:', swapId); + alert('Swap report not found'); + } + } catch (error) { + console.error('Failed to load swap report:', error); + alert('Failed to load swap report: ' + error.message); + } + } + + function buildSwapHistoryList() { + if (swapHistory.length === 0) { + return ` +
+
🔄
+

No Swap History

+

You haven't completed any coinswaps yet.

+ +
+ `; + } + + return ` +
${swapHistory - .map((swap) => { - const protocolLabel = getProtocolLabel(swap); - const isFailed = swap.status === 'failed'; + .map((swap, index) => { + const btcAmount = satsToBtc(swap.amount); + const outputBtc = satsToBtc(swap.totalOutputAmount); + const timeAgo = formatRelativeTime(swap.completedAt); + const dateStr = formatDate(swap.completedAt); + const duration = formatDuration(swap.durationSeconds); return ` -
-
-

Coinswap

-

${swap.hops} hops • ${swap.makersCount} makers

+
+
+ +
+
-
- - ${isFailed ? 'Failed' : 'Completed'} - + + +
+
+ Coinswap + Completed + ${swap.hops} hops +
+
+ ${timeAgo} + + ${dateStr} + + ${duration} +
+
+ + +
+
${btcAmount} BTC
+
${swap.amount.toLocaleString()} sats
+ + +
+ + + +
+
+ + +
- - ${protocolLabel} - + Makers +

${swap.makersCount}

-

${satsToBtc(swap.amount)} BTC

-

${swap.amount.toLocaleString()} sats

+ Fee +

${swap.feePercentage?.toFixed(2) || '0.00'}%

-

${(swap.totalFee || 0).toLocaleString()} sats

-

${(swap.feePercentage || 0).toFixed(2)}%

+ Total Fee +

${(swap.totalFee || 0).toLocaleString()} sats

-

${formatRelativeTime(swap.completedAt)}

-

${formatDate(swap.completedAt)} • ${formatDuration(swap.durationSeconds)}

+ Output +

${outputBtc} BTC

- `; +
+ `; }) .join('')}
-
- `; -} - -export async function SwapHistoryComponent(container) { - if (container.querySelector('#swap-history-content')) return; - - let swapHistory = []; - let stats = summarizeSwapHistory([]); - let loadError = null; - - try { - swapHistory = await loadSwapHistory(); - stats = summarizeSwapHistory(swapHistory); - } catch (error) { - loadError = error; + `; } - const content = document.createElement('div'); - content.id = 'swap-history-content'; + // Calculate stats + const totalSwaps = swapHistory.length; + const totalVolume = swapHistory.reduce((sum, s) => sum + (s.amount || 0), 0); + const totalFees = swapHistory.reduce((sum, s) => sum + (s.totalFee || 0), 0); + const avgHops = + totalSwaps > 0 + ? ( + swapHistory.reduce((sum, s) => sum + (s.hops || 0), 0) / totalSwaps + ).toFixed(1) + : 0; + content.innerHTML = ` -
+
+
-

Swap History

-

View all your completed and failed coinswaps

-
- - ${ - loadError - ? ` -
-

Unable to load swap history

-

${loadError.message || 'Please try again.'}

+
+
+

Swap History

+

View all your completed coinswap transactions

+
+ ${ + totalSwaps > 0 + ? ` + + ` + : '' + }
- ` - : '' - } +
+ ${ - stats.totalSwaps > 0 + totalSwaps > 0 ? `

Total Swaps

-

${stats.totalSwaps}

+

${totalSwaps}

-

Total Amount

-

${satsToBtc(stats.totalAmount)} BTC

+

Total Volume

+

${satsToBtc(totalVolume)} BTC

Total Fees Paid

-

${stats.totalFees.toLocaleString()} sats

+

${totalFees.toLocaleString()} sats

-

Avg Fee Paid

-

${stats.avgFeePaid.toLocaleString()} sats

+

Avg. Hops

+

${avgHops}

` : '' } +
- ${loadError ? '' : buildSwapHistoryMarkup(swapHistory)} + ${buildSwapHistoryList()}
`; container.appendChild(content); + // Event Listeners content.querySelector('#back-to-swap')?.addEventListener('click', () => { import('./Swap.js').then((module) => { container.innerHTML = ''; @@ -241,38 +364,31 @@ export async function SwapHistoryComponent(container) { }); }); - content.querySelectorAll('.swap-history-row').forEach((row) => { - row.addEventListener('click', async () => { - try { - const swapId = row.dataset.swapId; - const result = await window.api.swapReports.get(swapId); - - if (!result.success || !result.report) { - throw new Error(`Swap report not found for ${swapId}`); - } + content.querySelector('#start-first-swap')?.addEventListener('click', () => { + import('./Swap.js').then((module) => { + container.innerHTML = ''; + module.SwapComponent(container); + }); + }); - const module = await import('./SwapReport.js'); + content.querySelector('#clear-history')?.addEventListener('click', async () => { + if ( + confirm( + 'Are you sure you want to clear all swap history? This cannot be undone.' + ) + ) { + await SwapStateManager.clearSwapHistory(); + // Re-render the component + container.innerHTML = ''; + SwapHistoryComponent(container); + } + }); - container.innerHTML = ''; - const fullReport = { - ...result.report, - ...result.report.report, - protocol: result.report.protocol ?? 'v1', - isTaproot: result.report.isTaproot ?? false, - protocolVersion: result.report.protocolVersion ?? 1, - }; - module.SwapReportComponent(container, fullReport); - } catch (error) { - console.error('Failed to load swap report:', error); - container.innerHTML = ` -
-
-

Unable to open swap report

-

${error.message || 'Please try again.'}

-
-
- `; - } + // Click handlers for swap rows + content.querySelectorAll('.swap-history-row').forEach((row) => { + row.addEventListener('click', () => { + const swapId = row.dataset.swapId; + viewSwapReport(swapId); }); }); } diff --git a/src/components/swap/SwapReport.js b/src/components/swap/SwapReport.js index df9f063..caab566 100644 --- a/src/components/swap/SwapReport.js +++ b/src/components/swap/SwapReport.js @@ -21,6 +21,36 @@ export function SwapReportComponent(container, swapReport) { return; } + const toNumber = (value, fallback = 0) => { + const normalized = Number(value); + return Number.isFinite(normalized) ? normalized : fallback; + }; + + const rawTotalMakerFees = toNumber( + swapReport.totalMakerFees ?? swapReport.total_maker_fees, + 0 + ); + const rawMiningFee = toNumber( + swapReport.miningFee ?? swapReport.mining_fee, + 0 + ); + const rawFeePaidOrEarned = toNumber( + swapReport.fee_paid_or_earned ?? swapReport.feePaidOrEarned, + NaN + ); + const providedTotalFee = toNumber( + swapReport.totalFee ?? swapReport.total_fee, + NaN + ); + const derivedTotalFee = Number.isFinite(rawFeePaidOrEarned) + ? Math.abs(rawFeePaidOrEarned) + : rawTotalMakerFees + rawMiningFee; + const rawTotalFee = + Number.isFinite(providedTotalFee) && + (providedTotalFee > 0 || derivedTotalFee <= 0) + ? providedTotalFee + : derivedTotalFee; + // Extract values with safe defaults const report = { swapId: swapReport.swapId || swapReport.swap_id || 'unknown', @@ -38,11 +68,17 @@ export function SwapReportComponent(container, swapReport) { swapReport.totalFundingTxs || swapReport.total_funding_txs || 0, fundingTxidsByHop: swapReport.fundingTxidsByHop || swapReport.funding_txids_by_hop || [], - totalFee: swapReport.totalFee || swapReport.total_fee || 0, - totalMakerFees: - swapReport.totalMakerFees || swapReport.total_maker_fees || 0, - miningFee: swapReport.miningFee || swapReport.mining_fee || 0, - feePercentage: swapReport.feePercentage || swapReport.fee_percentage || 0, + totalFee: rawTotalFee, + totalMakerFees: rawTotalMakerFees, + miningFee: rawMiningFee, + feePercentage: + swapReport.feePercentage || + swapReport.fee_percentage || + ((swapReport.targetAmount ?? swapReport.target_amount ?? 0) > 0 + ? (rawTotalFee / + (swapReport.targetAmount ?? swapReport.target_amount ?? 0)) * + 100 + : 0), makerFeeInfo: swapReport.makerFeeInfo || swapReport.maker_fee_info || [], inputUtxos: swapReport.inputUtxos || swapReport.input_utxos || [], outputRegularUtxos: diff --git a/src/components/swap/SwapStateManager.js b/src/components/swap/SwapStateManager.js index 2ed417e..ad412cb 100644 --- a/src/components/swap/SwapStateManager.js +++ b/src/components/swap/SwapStateManager.js @@ -151,6 +151,24 @@ export const SwapStateManager = { console.log('Swap marked as completed and cleared from active state'); }, + async getSwapHistory() { + try { + const state = await this.loadState(); + return state[STORAGE_KEYS.SWAP_HISTORY] || []; + } catch (error) { + console.error('Error getting swap history:', error); + return []; + } + }, + + async clearSwapHistory() { + const state = await this.loadState(); + delete state[STORAGE_KEYS.SWAP_HISTORY]; + await this.saveState(state); + + console.log('Swap history cleared'); + }, + // Clear all swap data async clearSwapData() { const state = await this.loadState(); diff --git a/src/styles/output.css b/src/styles/output.css index 9437533..612b70f 100644 --- a/src/styles/output.css +++ b/src/styles/output.css @@ -44,7 +44,6 @@ --spacing: 0.25rem; --container-md: 28rem; --container-2xl: 42rem; - --container-3xl: 48rem; --container-5xl: 64rem; --container-6xl: 72rem; --container-7xl: 80rem; @@ -282,9 +281,6 @@ .bottom-4 { bottom: calc(var(--spacing) * 4); } - .z-10 { - z-index: 10; - } .z-50 { z-index: 50; } @@ -324,9 +320,6 @@ .mx-auto { margin-inline: auto; } - .mt-0\.5 { - margin-top: calc(var(--spacing) * 0.5); - } .mt-1 { margin-top: calc(var(--spacing) * 1); } @@ -444,9 +437,6 @@ .h-20 { height: calc(var(--spacing) * 20); } - .h-24 { - height: calc(var(--spacing) * 24); - } .h-40 { height: calc(var(--spacing) * 40); } @@ -546,6 +536,12 @@ .min-w-0 { min-width: calc(var(--spacing) * 0); } + .min-w-\[180px\] { + min-width: 180px; + } + .min-w-max { + min-width: max-content; + } .flex-1 { flex: 1; } @@ -555,10 +551,6 @@ .shrink-0 { flex-shrink: 0; } - .-translate-x-1\/2 { - --tw-translate-x: calc(calc(1/2 * 100%) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } .-translate-y-1\/2 { --tw-translate-y: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -575,9 +567,6 @@ .animate-spin { animation: var(--animate-spin); } - .cursor-help { - cursor: help; - } .cursor-not-allowed { cursor: not-allowed; } @@ -596,9 +585,6 @@ .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } - .grid-cols-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } .grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); } @@ -759,9 +745,6 @@ .rounded { border-radius: 0.25rem; } - .rounded-2xl { - border-radius: var(--radius-2xl); - } .rounded-full { border-radius: calc(infinity * 1px); } @@ -787,10 +770,6 @@ border-style: var(--tw-border-style); border-width: 2px; } - .border-4 { - border-style: var(--tw-border-style); - border-width: 4px; - } .border-t { border-top-style: var(--tw-border-style); border-top-width: 1px; @@ -892,24 +871,12 @@ border-color: color-mix(in oklab, var(--color-yellow-500) 30%, transparent); } } - .border-yellow-500\/50 { - border-color: color-mix(in srgb, oklch(79.5% 0.184 86.047) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-yellow-500) 50%, transparent); - } - } .bg-\[\#0f1419\] { background-color: #0f1419; } - .bg-\[\#0f1419\]\/90 { - background-color: color-mix(in oklab, #0f1419 90%, transparent); - } .bg-\[\#1a2332\] { background-color: #1a2332; } - .bg-\[\#1a2332\]\/80 { - background-color: color-mix(in oklab, #1a2332 80%, transparent); - } .bg-\[\#242d3d\] { background-color: #242d3d; } @@ -1092,10 +1059,6 @@ --tw-gradient-position: to right in oklab; background-image: linear-gradient(var(--tw-gradient-stops)); } - .from-\[\#0a0f16\] { - --tw-gradient-from: #0a0f16; - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - } .from-\[\#1a2332\] { --tw-gradient-from: #1a2332; --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); @@ -1113,10 +1076,6 @@ --tw-gradient-to: #0f1419; --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); } - .to-\[\#1a2332\] { - --tw-gradient-to: #1a2332; - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - } .to-\[\#FF6B35\] { --tw-gradient-to: #FF6B35; --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); @@ -1268,10 +1227,6 @@ --tw-leading: var(--leading-relaxed); line-height: var(--leading-relaxed); } - .font-black { - --tw-font-weight: var(--font-weight-black); - font-weight: var(--font-weight-black); - } .font-bold { --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold); @@ -1292,10 +1247,6 @@ --tw-tracking: var(--tracking-wide); letter-spacing: var(--tracking-wide); } - .tracking-wider { - --tw-tracking: var(--tracking-wider); - letter-spacing: var(--tracking-wider); - } .break-words { overflow-wrap: break-word; } @@ -1350,12 +1301,6 @@ .text-orange-500 { color: var(--color-orange-500); } - .text-purple-200 { - color: var(--color-purple-200); - } - .text-purple-300 { - color: var(--color-purple-300); - } .text-purple-400 { color: var(--color-purple-400); } @@ -1430,10 +1375,6 @@ --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); } - .shadow-xl { - --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } .shadow-black\/30 { --tw-shadow-color: color-mix(in srgb, #000 30%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1607,13 +1548,6 @@ } } } - .hover\:bg-gray-700 { - &:hover { - @media (hover: hover) { - background-color: var(--color-gray-700); - } - } - } .hover\:bg-green-600 { &:hover { @media (hover: hover) { @@ -1774,11 +1708,6 @@ grid-template-columns: repeat(3, minmax(0, 1fr)); } } - .md\:flex { - @media (width >= 48rem) { - display: flex; - } - } .md\:grid-cols-2 { @media (width >= 48rem) { grid-template-columns: repeat(2, minmax(0, 1fr)); @@ -1814,11 +1743,6 @@ grid-template-columns: repeat(5, minmax(0, 1fr)); } } - .xl\:grid-cols-4 { - @media (width >= 80rem) { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - } .xl\:grid-cols-\[1\.5fr_1fr\] { @media (width >= 80rem) { grid-template-columns: 1.5fr 1fr;