255 lines
15 KiB
HTML
255 lines
15 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||
<title>Toadstool Cottage Counter</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600;700&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="assets/icons/appicon-32x32.png">
|
||
<link rel="icon" type="image/png" sizes="128x128" href="assets/icons/appicon-128x128.png">
|
||
<link rel="apple-touch-icon" href="assets/icons/appicon-256x256.png">
|
||
<link rel="manifest" href="assets/site.webmanifest">
|
||
<meta name="theme-color" content="#e4e8d5">
|
||
<link rel="stylesheet" href="assets/style.css">
|
||
</head>
|
||
<body>
|
||
|
||
<header>
|
||
<div class="brand">
|
||
<img class="brand-icon" src="assets/icons/appicon-128x128.png" alt="Toadstool Cottage Counter icon">
|
||
<h1 id="appTitle">Toadstool Cottage Counter</h1>
|
||
</div>
|
||
<div class="header-controls">
|
||
<button class="header-btn hidden" id="installBtn" title="Install app"><i class="fa-solid fa-download"></i></button>
|
||
<button class="header-btn" id="motionBtn" onclick="toggleAnimations()" title="Toggle Animations"><i class="fa-solid fa-wand-magic-sparkles"></i></button>
|
||
<button class="header-btn" id="themeBtn" onclick="toggleTheme()" title="Toggle Dark Mode"><i class="fa-solid fa-moon"></i></button>
|
||
<button class="header-btn" id="focusBtn" onclick="toggleFocusMode()" title="Focus Mode (Keeps Screen On)"><i class="fa-solid fa-eye"></i></button>
|
||
<button class="header-btn" id="saveLoadBtn" onclick="openSaveModal()" title="Save/Load"><i class="fa-solid fa-floppy-disk"></i></button>
|
||
</div>
|
||
</header>
|
||
<input type="file" id="importFile" accept="application/json" class="hidden-input" />
|
||
|
||
<div class="container" id="app"></div>
|
||
|
||
<button class="fab" onclick="openModal('addProject')">+</button>
|
||
<button class="fab fab-pattern" onclick="openPatternComposer()" title="Open Pattern Composer"><i class="fa-solid fa-swatchbook"></i></button>
|
||
|
||
<div class="modal-overlay" id="modalOverlay">
|
||
<div class="modal-content">
|
||
<h3 class="modal-title" id="modalTitle">Title</h3>
|
||
<input type="text" class="modal-input" id="modalInput" autocomplete="off">
|
||
<div class="pattern-picker" id="patternPicker">
|
||
<label for="patternSelect">Pattern (optional)</label>
|
||
<select id="patternSelect">
|
||
<option value="">No pattern</option>
|
||
</select>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button class="modal-btn btn-cancel" onclick="closeModal()">Cancel</button>
|
||
<button class="modal-btn btn-save" onclick="saveModal()">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="color-overlay" id="colorOverlay">
|
||
<div class="color-modal">
|
||
<h3 class="color-title">Pick a color</h3>
|
||
<div class="color-grid" id="colorGrid"></div>
|
||
<div class="color-custom">
|
||
<label for="customColorInput">Custom:</label>
|
||
<input type="color" id="customColorInput" />
|
||
</div>
|
||
<button class="modal-btn btn-cancel" onclick="closeColorPicker()">Close</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="save-overlay" id="saveOverlay">
|
||
<div class="save-modal">
|
||
<h3 class="color-title">Save or Load</h3>
|
||
<p class="save-subtext">Choose projects to include:</p>
|
||
<div class="save-list" id="saveList"></div>
|
||
<div class="save-actions">
|
||
<button class="modal-btn btn-cancel" onclick="closeSaveModal()">Cancel</button>
|
||
<button class="modal-btn btn-save" onclick="exportSelected()">Save</button>
|
||
<button class="modal-btn btn-save" onclick="triggerImport()">Load</button>
|
||
</div>
|
||
<div class="import-selection hidden" id="importSelection">
|
||
<p class="save-subtext">Imported file projects:</p>
|
||
<div class="save-list" id="importList"></div>
|
||
<div class="save-actions">
|
||
<button class="modal-btn btn-cancel" onclick="cancelImportSelection()">Cancel</button>
|
||
<button class="modal-btn btn-save" onclick="applyImportSelection()">Add Selected</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pattern-overlay" id="patternOverlay">
|
||
<div class="pattern-sheet">
|
||
<div class="pattern-sheet-header">
|
||
<div class="pattern-sheet-title">
|
||
<h2>Pattern Composer</h2>
|
||
<p class="pattern-sheet-subtitle">Draft rows plus materials, gauge, and abbreviations.</p>
|
||
</div>
|
||
<div class="pattern-modes">
|
||
<button class="pattern-mode" data-mode="crochet" onclick="setPatternMode('crochet')">Crochet</button>
|
||
<button class="pattern-mode" data-mode="knit" onclick="setPatternMode('knit')">Knit</button>
|
||
</div>
|
||
<div class="pattern-save-indicator" id="patternSaveIndicator">Saved</div>
|
||
<button class="pattern-close" onclick="closePatternComposer()">×</button>
|
||
</div>
|
||
<div class="pattern-body">
|
||
<div class="pattern-tabs">
|
||
<button class="pattern-tab" data-tab="info" onclick="showPatternTab('info')">Pattern Info</button>
|
||
<button class="pattern-tab" data-tab="steps" onclick="showPatternTab('steps')">Steps</button>
|
||
</div>
|
||
<div class="pattern-section" data-section="info">
|
||
<label class="field-label" for="patternTitle">Title</label>
|
||
<input id="patternTitle" type="text" placeholder="e.g., Baby Fox Plush">
|
||
<label class="field-label" for="patternDesigner">Designer / Credits</label>
|
||
<input id="patternDesigner" type="text" placeholder="Your name or shop">
|
||
<label class="field-label" for="patternMaterials">Materials (one per line)</label>
|
||
<textarea id="patternMaterials" placeholder="Yarn (Color A) – worsted Yarn (Color B) – accent Hook – 4.0 mm Safety eyes, stuffing, needle"></textarea>
|
||
<div class="field-group-inline">
|
||
<div>
|
||
<label class="field-label" for="patternGaugeSts">Stitches / 4in (10cm)</label>
|
||
<input id="patternGaugeSts" type="text" placeholder="e.g., 16 sc">
|
||
</div>
|
||
<div>
|
||
<label class="field-label" for="patternGaugeRows">Rows / 4in (10cm)</label>
|
||
<input id="patternGaugeRows" type="text" placeholder="e.g., 18 rows">
|
||
</div>
|
||
</div>
|
||
<label class="field-label" for="patternGaugeHook">Hook / Needles</label>
|
||
<input id="patternGaugeHook" type="text" placeholder="e.g., 4.0 mm hook">
|
||
<label class="field-label" for="patternSize">Finished size</label>
|
||
<input id="patternSize" type="text" placeholder="Approx. 6 in / 15 cm tall">
|
||
<label class="field-label" for="patternGauge">Gauge (extra notes)</label>
|
||
<textarea id="patternGauge" placeholder="Magic ring start; or any extra gauge notes"></textarea>
|
||
<div class="abbrev-head">
|
||
<label class="field-label" for="patternAbbrev">Abbreviations</label>
|
||
<button class="secondary" onclick="loadDefaultAbbrev()">Load defaults</button>
|
||
</div>
|
||
<div id="patternAbbrevList" class="abbrev-grid"></div>
|
||
<textarea id="patternAbbrev" placeholder="sc – single crochet dc – double crochet inc – increase k – knit p – purl"></textarea>
|
||
<label class="field-label" for="patternStitches">Stitch guide / special stitches</label>
|
||
<textarea id="patternStitches" placeholder="Magic ring: ... Invisible decrease: ... Kfb: knit front and back ..."></textarea>
|
||
<label class="field-label" for="patternNotes">Notes / finishing</label>
|
||
<textarea id="patternNotes" placeholder="Assembly, finishing, safety warnings, credits..."></textarea>
|
||
<div class="pattern-row-actions pattern-footer">
|
||
<button onclick="clearPatternOutput()">Clear pattern</button>
|
||
<button class="secondary" onclick="exportPatternJSON()">Export JSON</button>
|
||
<button class="secondary" onclick="importPatternJSON()">Import JSON</button>
|
||
<button class="primary" onclick="exportPatternPDF()">Export PDF</button>
|
||
</div>
|
||
</div>
|
||
<div class="pattern-section" data-section="steps">
|
||
<div class="pattern-steps-head">
|
||
<h4>Steps</h4>
|
||
<button class="primary" onclick="addStep()">+ Step</button>
|
||
</div>
|
||
<div id="patternSteps"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pattern-overlay" id="patternOverlay">
|
||
<div class="pattern-sheet">
|
||
<div class="pattern-sheet-header">
|
||
<div class="pattern-sheet-title">
|
||
<h2>Pattern Composer</h2>
|
||
<p class="pattern-sheet-subtitle">Draft rows plus materials, gauge, and abbreviations.</p>
|
||
</div>
|
||
<div class="pattern-modes">
|
||
<button class="pattern-mode" data-mode="crochet" onclick="setPatternMode('crochet')">Crochet</button>
|
||
<button class="pattern-mode" data-mode="knit" onclick="setPatternMode('knit')">Knit</button>
|
||
</div>
|
||
<button class="pattern-close" onclick="closePatternComposer()">×</button>
|
||
</div>
|
||
<div class="pattern-body">
|
||
<div class="pattern-tabs">
|
||
<button class="pattern-tab" data-tab="meta" onclick="showPatternTab('meta')">Cover</button>
|
||
<button class="pattern-tab" data-tab="materials" onclick="showPatternTab('materials')">Materials</button>
|
||
<button class="pattern-tab" data-tab="gauge" onclick="showPatternTab('gauge')">Gauge/Size</button>
|
||
<button class="pattern-tab" data-tab="abbrev" onclick="showPatternTab('abbrev')">Abbrev</button>
|
||
<button class="pattern-tab" data-tab="stitches" onclick="showPatternTab('stitches')">Stitches</button>
|
||
<button class="pattern-tab" data-tab="steps" onclick="showPatternTab('steps')">Steps</button>
|
||
<button class="pattern-tab" data-tab="notes" onclick="showPatternTab('notes')">Notes</button>
|
||
</div>
|
||
<div class="pattern-section" data-section="meta">
|
||
<label class="field-label" for="patternTitle">Title</label>
|
||
<input id="patternTitle" type="text" placeholder="e.g., Baby Fox Plush">
|
||
<label class="field-label" for="patternDesigner">Designer / Credits</label>
|
||
<input id="patternDesigner" type="text" placeholder="Your name or shop">
|
||
</div>
|
||
<div class="pattern-section" data-section="materials">
|
||
<label class="field-label" for="patternMaterials">Materials (one per line)</label>
|
||
<textarea id="patternMaterials" placeholder="Yarn (Color A) – worsted\nYarn (Color B) – accent\nHook – 4.0 mm\nSafety eyes, stuffing, needle"></textarea>
|
||
</div>
|
||
<div class="pattern-section" data-section="gauge">
|
||
<label class="field-label" for="patternGauge">Gauge</label>
|
||
<textarea id="patternGauge" placeholder="e.g., 16 sc x 18 rows = 4”/10 cm with 4.0 mm hook"></textarea>
|
||
<label class="field-label" for="patternSize">Finished size</label>
|
||
<input id="patternSize" type="text" placeholder="Approx. 6 in / 15 cm tall">
|
||
</div>
|
||
<div class="pattern-section" data-section="abbrev">
|
||
<label class="field-label" for="patternAbbrev">Abbreviations</label>
|
||
<textarea id="patternAbbrev" placeholder="sc – single crochet\ndc – double crochet\ninc – increase\nk – knit\np – purl"></textarea>
|
||
</div>
|
||
<div class="pattern-section" data-section="stitches">
|
||
<label class="field-label" for="patternStitches">Stitch guide / special stitches</label>
|
||
<textarea id="patternStitches" placeholder="Magic ring: ... Invisible decrease: ... Kfb: knit front and back ..."></textarea>
|
||
</div>
|
||
<div class="pattern-section" data-section="steps">
|
||
<div class="pattern-row-info">Row <span id="patternRowNumber">1</span></div>
|
||
<div class="pattern-buttons">
|
||
<button onclick="addPatternToken('sc')">sc</button>
|
||
<button onclick="addPatternToken('hdc')">hdc</button>
|
||
<button onclick="addPatternToken('dc')">dc</button>
|
||
<button onclick="addPatternToken('ch')">ch</button>
|
||
<button onclick="addPatternToken('sl st')">sl st</button>
|
||
<button onclick="addPatternToken('inc')">inc</button>
|
||
<button onclick="addPatternToken('dec')">dec</button>
|
||
<button onclick="addPatternToken('k')">k</button>
|
||
<button onclick="addPatternToken('p')">p</button>
|
||
<button onclick="addPatternToken('yo')">yo</button>
|
||
<button onclick="addPatternToken('k2tog')">k2tog</button>
|
||
<button onclick="addPatternToken('[ ] x')">[ ] x</button>
|
||
</div>
|
||
<div class="pattern-row-editor">
|
||
<textarea id="patternLine" placeholder="Build a row with the buttons above or type manually..."></textarea>
|
||
<div class="pattern-row-actions">
|
||
<button onclick="clearPatternLine()">Clear line</button>
|
||
<button class="primary" onclick="addPatternRow()">Add row</button>
|
||
</div>
|
||
</div>
|
||
<div class="pattern-steps-head">
|
||
<h4>Steps</h4>
|
||
<button class="primary" onclick="addStep()">+ Step</button>
|
||
</div>
|
||
<div id="patternSteps"></div>
|
||
</div>
|
||
<div class="pattern-section" data-section="notes">
|
||
<label class="field-label" for="patternNotes">Notes / finishing</label>
|
||
<textarea id="patternNotes" placeholder="Assembly, finishing, safety warnings, credits..."></textarea>
|
||
</div>
|
||
<div class="pattern-output">
|
||
<label for="patternOutput">Pattern draft (rows)</label>
|
||
<textarea id="patternOutput" placeholder="Rows will appear here as you add them..."></textarea>
|
||
<div class="pattern-row-actions">
|
||
<button onclick="clearPatternOutput()">Clear pattern</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="assets/app.js"></script>
|
||
<footer class="footer-bg" aria-hidden="true"></footer>
|
||
</body>
|
||
</html>
|