Deployment fixes, add HPP logo

This commit is contained in:
2026-05-04 22:21:07 +12:00
parent 2799946091
commit ebee72d4df
24 changed files with 768 additions and 45 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "data-entry-app-frontend",
"version": "0.1.4",
"version": "0.1.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-entry-app-frontend",
"version": "0.1.4",
"version": "0.1.5",
"devDependencies": {
"@sveltejs/adapter-auto": "^3.2.0",
"@sveltejs/adapter-node": "^5.2.12",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "data-entry-app-frontend",
"version": "0.1.4",
"version": "0.1.5",
"private": true,
"type": "module",
"scripts": {
+39 -21
View File
@@ -3,8 +3,8 @@
import { invalidateAll } from '$app/navigation';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import Lean101Logo from '$lib/components/Lean101Logo.svelte';
import { clientSession, hasModuleAccess, sessionHydrated } from '$lib/session';
import { featureFlags } from '$lib/features';
import { onMount, tick } from 'svelte';
import packageInfo from '../../../package.json';
@@ -24,7 +24,12 @@
};
const dashboardItem: NavItem = { href: '/', label: 'Dashboard', shortLabel: 'DB', icon: 'home', moduleKey: 'dashboard' };
const mixCalculatorItem: NavItem = { href: '/mix-calculator', label: 'Mix Calculator', shortLabel: 'MC', moduleKey: 'mix_calculator' };
const mixCalculatorItem: NavItem = {
href: featureFlags.mixCalculatorSessionHistory ? '/mix-calculator' : '/mix-calculator/new',
label: 'Mix Calculator',
shortLabel: 'MC',
moduleKey: 'mix_calculator'
};
const workingDocumentItems: NavItem[] = [
{ href: '/raw-materials', label: 'Raw Materials', shortLabel: 'RM', moduleKey: 'raw_materials' },
{ href: '/mixes', label: 'Mix Master', shortLabel: 'MM', moduleKey: 'mix_master' },
@@ -64,12 +69,16 @@
description: 'Start a new costing worksheet for Hunter Premium Produce.',
keywords: 'new mix create worksheet hunter premium produce formula'
},
{
href: '/mix-calculator',
label: 'Open Mix Calculator',
description: 'Review saved production sessions and batch calculations.',
keywords: 'mix calculator production sessions batch bags client product'
},
...(featureFlags.mixCalculatorSessionHistory
? [
{
href: '/mix-calculator',
label: 'Open Mix Calculator',
description: 'Review saved production sessions and batch calculations.',
keywords: 'mix calculator production sessions batch bags client product'
}
]
: []),
{
href: '/mix-calculator/new',
label: 'Create Mix Calculation',
@@ -281,7 +290,9 @@
Promise.all([
hasModuleAccess(session, 'products') ? api.products() : Promise.resolve([]),
hasModuleAccess(session, 'mix_master') ? api.mixes() : Promise.resolve([]),
hasModuleAccess(session, 'mix_calculator') ? api.mixCalculatorSessions() : Promise.resolve([])
featureFlags.mixCalculatorSessionHistory && hasModuleAccess(session, 'mix_calculator')
? api.mixCalculatorSessions()
: Promise.resolve([])
])
.then(([products, mixes, sessions]) => {
if (seededSearchToken !== token) {
@@ -382,7 +393,7 @@
<aside class="sidebar">
<div class="brand-row">
<a class="brand" href="/">
<Lean101Logo className="sidebar-logo" showTagline={false} />
<img class="sidebar-logo" src="/logo-hsf.png" alt="Hunter Premium Produce" />
</a>
</div>
@@ -421,7 +432,9 @@
{#if visibleMixCalculatorItem}
<a class:active={matchesRoute(visibleMixCalculatorItem.href, page.url.pathname)} href={visibleMixCalculatorItem.href}>
<span class="nav-icon">{visibleMixCalculatorItem.shortLabel}</span>
<span class="nav-icon">
<span class="nav-icon-mask" style="--nav-icon-url: url('/icons/calculator.svg');" aria-hidden="true"></span>
</span>
<span>{visibleMixCalculatorItem.label}</span>
</a>
{/if}
@@ -560,7 +573,7 @@
<div class="menu-panel quick-fab-panel">
<a href="/mixes">Open mix costing</a>
<a href="/mixes/new">Create mix worksheet</a>
<a href="/mix-calculator">Open mix calculator</a>
<a href={featureFlags.mixCalculatorSessionHistory ? '/mix-calculator' : '/mix-calculator/new'}>Open mix calculator</a>
<a href="/mix-calculator/new">Create mix session</a>
<a href="/products">Review delivered pricing</a>
<button type="button" onclick={() => openPalette('')}>Search the workspace</button>
@@ -687,7 +700,9 @@
{#if visibleMixCalculatorItem}
<a class:active={matchesRoute(visibleMixCalculatorItem.href, page.url.pathname)} href={visibleMixCalculatorItem.href} onclick={() => (navOpen = false)}>
<span class="nav-icon">{visibleMixCalculatorItem.shortLabel}</span>
<span class="nav-icon">
<span class="nav-icon-mask" style="--nav-icon-url: url('/icons/calculator.svg');" aria-hidden="true"></span>
</span>
<span>{visibleMixCalculatorItem.label}</span>
</a>
{/if}
@@ -918,16 +933,19 @@
letter-spacing: 0.04em;
}
.sidebar :global(.sidebar-logo) {
width: min(100%, 12.2rem);
.nav-icon-mask {
display: inline-block;
width: 60%;
height: 60%;
background-color: currentColor;
-webkit-mask: var(--nav-icon-url) center / contain no-repeat;
mask: var(--nav-icon-url) center / contain no-repeat;
}
.sidebar :global(.sidebar-logo .logo-copy strong) {
font-size: 1.6rem;
}
.sidebar :global(.sidebar-logo .logo-mark) {
width: 2.6rem;
.sidebar .sidebar-logo {
width: min(100%, 13.5rem);
height: auto;
display: block;
}
.nav-toggle,
@@ -1,6 +1,7 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { api } from '$lib/api';
import { featureFlags } from '$lib/features';
import { clientSession, hasModuleAccess } from '$lib/session';
import type {
MixCalculatorCreateInput,
@@ -169,7 +170,25 @@
}
}
async function saveSession(mode: 'update' | 'create') {
function clearForm() {
clientName = options.clients[0] ?? '';
productId = 0;
mixDate = todayIso;
batchSizeKg = '';
preparedByName = $clientSession?.name ?? '';
notes = '';
preview = null;
formError = '';
formSuccess = '';
}
function printPreview() {
if (typeof window !== 'undefined') {
window.print();
}
}
async function saveSession(mode: 'update' | 'create', destination: 'detail' | 'print' = 'detail') {
const payload = buildPayload();
if (!payload) {
return;
@@ -182,7 +201,8 @@
? await api.updateMixCalculatorSession(initialSession.id, payload)
: await api.createMixCalculatorSession(payload);
await goto(`/mix-calculator/${saved.id}`);
const target = destination === 'print' ? `/mix-calculator/${saved.id}/print` : `/mix-calculator/${saved.id}`;
await goto(target);
} catch (error) {
formError = error instanceof Error ? error.message : 'Unable to save the mix calculator session.';
saveLoading = false;
@@ -195,17 +215,24 @@
<p class="eyebrow">Mix Calculator</p>
<h2>Edit access is required to create a new session.</h2>
<p>View-only users can open saved sessions from history, but cannot create or update production calculations.</p>
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{#if featureFlags.mixCalculatorSessionHistory}
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{/if}
</section>
{:else}
<section class="page-intro">
<div>
<p class="eyebrow">Mix Calculator</p>
<p class="eyebrow">
<span class="eyebrow-icon" style="--button-icon-url: url('/icons/calculator.svg');" aria-hidden="true"></span>
<span>Mix Calculator</span>
</p>
<h2>{isExistingSession ? 'Edit saved mix session' : 'New mix calculation session'}</h2>
<p>Scale a saved product mix by batch size, review required raw materials, then save the session for history and printing.</p>
</div>
<div class="header-actions">
<a class="secondary-button" href="/mix-calculator">Session history</a>
{#if featureFlags.mixCalculatorSessionHistory}
<a class="secondary-button" href="/mix-calculator">Session history</a>
{/if}
{#if initialSession}
<a class="secondary-button" href={`/mix-calculator/${initialSession.id}/print`}>Printable view</a>
{/if}
@@ -288,18 +315,36 @@
{#if canEdit}
<div class="action-row">
<button class="primary-button" disabled={previewLoading || saveLoading} type="button" onclick={calculatePreview}>
{previewLoading ? 'Calculating...' : 'Calculate mix'}
<span class="button-icon" style="--button-icon-url: url('/icons/calculator.svg');" aria-hidden="true"></span>
<span>{previewLoading ? 'Calculating...' : 'Calculate mix'}</span>
</button>
<button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession(isExistingSession ? 'update' : 'create')}>
{saveLoading ? 'Saving...' : isExistingSession ? 'Save changes' : 'Save session'}
</button>
{#if featureFlags.mixCalculatorSessionSave}
<button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession(isExistingSession ? 'update' : 'create')}>
{saveLoading ? 'Saving...' : isExistingSession ? 'Save changes' : 'Save session'}
</button>
{#if initialSession}
<button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession('create')}>
Save as new
<button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession(isExistingSession ? 'update' : 'create', 'print')}>
<span class="button-icon" style="--button-icon-url: url('/icons/print.svg');" aria-hidden="true"></span>
<span>{saveLoading ? 'Saving...' : 'Save & print'}</span>
</button>
{#if initialSession}
<button class="secondary-button" disabled={saveLoading || previewLoading} type="button" onclick={() => saveSession('create')}>
Save as new
</button>
{/if}
{:else}
<button class="secondary-button" disabled={previewLoading || saveLoading || !preview} type="button" onclick={printPreview}>
<span class="button-icon" style="--button-icon-url: url('/icons/print.svg');" aria-hidden="true"></span>
<span>Print</span>
</button>
{/if}
<button class="secondary-button" disabled={previewLoading || saveLoading} type="button" onclick={clearForm}>
<span class="button-icon" style="--button-icon-url: url('/icons/trash.svg');" aria-hidden="true"></span>
<span>Clear</span>
</button>
</div>
{/if}
</article>
@@ -396,6 +441,92 @@
{/if}
</article>
</section>
{#if preview}
<section class="print-only" aria-hidden="true">
<article class="print-sheet">
<header class="print-header">
<div>
<p class="print-eyebrow">Mix Calculator</p>
<h1>{preview.product_name}</h1>
<p class="print-subtitle">{preview.client_name} · {preview.mix_name}</p>
</div>
<div class="print-meta">
<div>
<span>Mix date</span>
<strong>{formatDate(preview.mix_date)}</strong>
</div>
<div>
<span>Prepared by</span>
<strong>{preview.prepared_by_name}</strong>
</div>
</div>
</header>
<section class="print-summary">
<div>
<span>Batch size</span>
<strong>{formatNumber(preview.batch_size_kg, 2)}kg</strong>
</div>
<div>
<span>Total kilograms</span>
<strong>{formatNumber(preview.total_kg, 2)}kg</strong>
</div>
<div>
<span>Total bags</span>
<strong>{formatNumber(preview.total_bags, 2)}</strong>
</div>
<div>
<span>Unit size</span>
<strong>{formatNumber(preview.product_unit_size_kg, 2)}kg</strong>
</div>
</section>
{#if preview.notes}
<section class="print-notes">
<h2>Notes</h2>
<p>{preview.notes}</p>
</section>
{/if}
{#if preview.warnings.length}
<section class="print-warnings">
<h2>Warnings</h2>
{#each preview.warnings as warning}
<p>{warning}</p>
{/each}
</section>
{/if}
<section class="print-table">
<div class="print-table-header">
<h2>Required raw materials</h2>
<span>{preview.product_unit_of_measure} · {formatNumber(preview.product_unit_size_kg, 2)}kg per unit</span>
</div>
<table>
<thead>
<tr>
<th>Raw material</th>
<th>Mix %</th>
<th>Required kg</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
{#each preview.lines as line}
<tr>
<td>{line.raw_material_name}</td>
<td>{formatNumber(line.mix_percentage, 2)}%</td>
<td>{formatNumber(line.required_kg, 2)}kg</td>
<td>{line.unit}</td>
</tr>
{/each}
</tbody>
</table>
</section>
</article>
</section>
{/if}
{/if}
<style>
@@ -411,6 +542,18 @@
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
display: inline-flex;
align-items: center;
gap: 0.45rem;
}
.eyebrow-icon {
display: inline-block;
width: 0.95rem;
height: 0.95rem;
background-color: currentColor;
-webkit-mask: var(--button-icon-url) center / contain no-repeat;
mask: var(--button-icon-url) center / contain no-repeat;
}
.page-intro,
@@ -593,6 +736,7 @@
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.78rem 0.96rem;
border-radius: 0.9rem;
border: 1px solid var(--line-strong);
@@ -632,6 +776,16 @@
box-shadow: 0 10px 22px rgba(24, 38, 29, 0.08);
}
.button-icon {
display: inline-block;
width: 1rem;
height: 1rem;
background-color: currentColor;
-webkit-mask: var(--button-icon-url) center / contain no-repeat;
mask: var(--button-icon-url) center / contain no-repeat;
flex-shrink: 0;
}
button:disabled {
cursor: wait;
opacity: 0.7;
@@ -781,4 +935,151 @@
text-transform: uppercase;
}
}
.print-only {
display: none;
}
@media print {
:global(body) {
background: #fff !important;
margin: 0 !important;
}
:global(body *) {
visibility: hidden !important;
}
.print-only,
.print-only :global(*) {
visibility: visible !important;
}
.print-only {
display: block;
position: absolute;
inset: 0;
padding: 1.4cm;
background: #fff;
color: #1a2421;
font-family: inherit;
}
.print-sheet {
width: 100%;
}
.print-header {
display: flex;
justify-content: space-between;
gap: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid #cbd6cf;
}
.print-header h1 {
margin: 0.25rem 0 0.3rem;
font-size: 1.7rem;
}
.print-eyebrow {
color: #5f6f67;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
margin: 0;
}
.print-subtitle {
color: #5f6f67;
margin: 0;
}
.print-meta {
display: grid;
gap: 0.55rem;
min-width: 12rem;
}
.print-meta div,
.print-summary div {
display: grid;
gap: 0.1rem;
}
.print-meta span,
.print-summary span,
.print-table-header span {
color: #5f6f67;
font-size: 0.72rem;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.print-summary {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.85rem;
padding: 1rem 0;
border-bottom: 1px solid #cbd6cf;
}
.print-notes,
.print-warnings {
margin-top: 0.85rem;
padding: 0.75rem 0.9rem;
border: 1px solid #cbd6cf;
border-radius: 0.5rem;
}
.print-warnings {
border-color: #d8a76b;
background: #fff6e6;
color: #8b5b1e;
}
.print-notes h2,
.print-warnings h2,
.print-table-header h2 {
margin: 0 0 0.35rem;
font-size: 0.95rem;
}
.print-table {
margin-top: 1rem;
}
.print-table-header {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
margin-bottom: 0.5rem;
}
.print-table table {
width: 100%;
border-collapse: collapse;
}
.print-table th,
.print-table td {
padding: 0.55rem 0.5rem;
text-align: left;
border-bottom: 1px solid #cbd6cf;
font-size: 0.92rem;
}
.print-table th {
color: #5f6f67;
font-size: 0.72rem;
letter-spacing: 0.06em;
text-transform: uppercase;
}
@page {
margin: 1cm;
}
}
</style>
+13
View File
@@ -0,0 +1,13 @@
import { env } from '$env/dynamic/public';
function flagEnabled(value: string | undefined, defaultValue: boolean): boolean {
if (value === undefined || value === null || value.trim() === '') {
return defaultValue;
}
return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
}
export const featureFlags = {
mixCalculatorSessionHistory: flagEnabled(env.PUBLIC_MIX_CALCULATOR_SESSION_HISTORY, false),
mixCalculatorSessionSave: flagEnabled(env.PUBLIC_MIX_CALCULATOR_SESSION_SAVE, false)
};
+6 -6
View File
@@ -303,7 +303,7 @@
<div class="auth-card auth-card-loading">
<div class="auth-header">
<div class="client-logo-block">
<img class="hero-login-logo" src="/lean101-login-logo.png" alt="Lean 101" />
<img class="hero-login-logo" src="/logo-hsf.png" alt="Lean 101" />
<div class="client-logo-copy">
<p class="eyebrow">Client Workspace</p>
<strong>Hunter Premium Produce</strong>
@@ -327,7 +327,7 @@
<div class="auth-footer">
<div class="lean-brand">
<img class="footer-login-logo" src="/lean101-login-logo.png" alt="Lean 101" />
<img class="footer-login-logo" src="/logo-hsf.png" alt="Lean 101" />
</div>
<div class="auth-meta">
<span class="version-badge">
@@ -344,7 +344,7 @@
<div class="auth-card auth-card-login">
<div class="auth-header">
<div class="client-logo-block">
<img class="hero-login-logo" src="/lean101-login-logo.png" alt="Lean 101" />
<img class="hero-login-logo" src="/logo-hsf.png" alt="Lean 101" />
<div class="client-logo-copy">
<p class="eyebrow">Client Sign-In</p>
<strong>Hunter Premium Produce</strong>
@@ -389,7 +389,7 @@
<div class="auth-footer">
<div class="lean-brand">
<img class="footer-login-logo" src="/lean101-login-logo.png" alt="Lean 101" />
<img class="footer-login-logo" src="/logo-hsf.png" alt="Lean 101" />
</div>
<div class="auth-meta">
<span class="version-badge">
@@ -798,13 +798,13 @@
}
.hero-login-logo {
width: min(100%, 19rem);
width: min(100%, 24rem);
height: auto;
display: block;
}
.footer-login-logo {
width: 9.8rem;
width: 12rem;
height: auto;
display: block;
}
@@ -1,7 +1,13 @@
import { redirect } from '@sveltejs/kit';
import { api } from '$lib/api';
import { featureFlags } from '$lib/features';
import { getStoredClientSession, hasModuleAccess, hasStoredClientSession } from '$lib/session';
export async function load({ fetch }) {
if (!featureFlags.mixCalculatorSessionHistory) {
throw redirect(307, '/mix-calculator/new');
}
if (!hasStoredClientSession()) {
return {
sessions: []
@@ -1,5 +1,6 @@
<script lang="ts">
import MixCalculatorWorkspace from '$lib/components/MixCalculatorWorkspace.svelte';
import { featureFlags } from '$lib/features';
let { data } = $props();
</script>
@@ -11,7 +12,11 @@
<p class="eyebrow">Mix Calculator</p>
<h2>Session unavailable.</h2>
<p>The requested mix calculator session could not be loaded with the current access scope.</p>
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{#if featureFlags.mixCalculatorSessionHistory}
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{:else}
<a class="secondary-button" href="/mix-calculator/new">New mix session</a>
{/if}
</section>
{/if}
@@ -1,5 +1,6 @@
<script lang="ts">
import MixCalculatorPrintSheet from '$lib/components/MixCalculatorPrintSheet.svelte';
import { featureFlags } from '$lib/features';
let { data } = $props();
</script>
@@ -11,7 +12,11 @@
<p class="eyebrow">Mix Calculator</p>
<h2>Printable session unavailable.</h2>
<p>The saved session could not be loaded for printing.</p>
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{#if featureFlags.mixCalculatorSessionHistory}
<a class="secondary-button" href="/mix-calculator">Back to session history</a>
{:else}
<a class="secondary-button" href="/mix-calculator/new">New mix session</a>
{/if}
</section>
{/if}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M0 64C0 28.7 28.7 0 64 0L320 0c35.3 0 64 28.7 64 64l0 384c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64L0 64zM96 80l0 64c0 8.8 7.2 16 16 16l160 0c8.8 0 16-7.2 16-16l0-64c0-8.8-7.2-16-16-16L112 64c-8.8 0-16 7.2-16 16zm32 128a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm64 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm96-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM64 304a32 32 0 1 0 64 0 32 32 0 1 0 -64 0zm32 128a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm64-128a32 32 0 1 0 64 0 32 32 0 1 0 -64 0zm32 128a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm64-96l0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32z"/></svg>

After

Width:  |  Height:  |  Size: 895 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64l0 96 64 0 0-96 226.7 0L384 93.3l0 66.7 64 0 0-66.7c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0L128 0zM384 352l0 32 0 64-256 0 0-64 0-16 0-16 256 0zm64 32l32 0c17.7 0 32-14.3 32-32l0-96c0-35.3-28.7-64-64-64L64 192c-35.3 0-64 28.7-64 64l0 96c0 17.7 14.3 32 32 32l32 0 0 64c0 35.3 28.7 64 64 64l256 0c35.3 0 64-28.7 64-64l0-64zM432 248a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/></svg>

After

Width:  |  Height:  |  Size: 699 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB