Features: quarter-fold and flat 4-up layouts, 8 themes, 12 presets, font picker, text alignment, text size sliders, background/accent/text colour pickers, message page (left/right) toggle, A4/Letter paper size, tabbed sidebar UI, responsive mobile layout, localStorage persistence, and Beach Party Balloons branding support. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
213 lines
9.4 KiB
HTML
213 lines
9.4 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Card Studio — Printable Cards</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=Caveat:wght@400;700&family=Cinzel:wght@400;700&family=Dancing+Script:wght@400;700&family=Fredoka:wght@400;600&family=Lora:ital,wght@0,400;0,700;1,400&family=Montserrat:wght@400;700;800&family=Pacifico&family=Playfair+Display:ital,wght@0,400;0,700;0,800;1,400&family=Quicksand:wght@400;600;700&family=Raleway:ital,wght@0,400;0,700;1,400&family=Press+Start+2P&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body>
|
||
|
||
<header class="topbar no-print">
|
||
<div class="brand">
|
||
<h1>Card Studio</h1>
|
||
<span class="tag">printable cards</span>
|
||
</div>
|
||
<button class="btn primary" id="printBtn">Print card</button>
|
||
</header>
|
||
|
||
<div class="layout">
|
||
<aside class="controls no-print">
|
||
|
||
<div class="tabs" role="tablist" id="tabBar">
|
||
<button class="tab active" data-tab="design" role="tab" aria-selected="true">Design</button>
|
||
<button class="tab" data-tab="text" role="tab" aria-selected="false">Text</button>
|
||
<button class="tab" data-tab="options" role="tab" aria-selected="false">Options</button>
|
||
</div>
|
||
|
||
<!-- ── Design ─────────────────────────────────────── -->
|
||
<div class="tab-panel active" data-tab="design">
|
||
|
||
<div class="group">
|
||
<span class="lbl">Paper size</span>
|
||
<div class="seg" id="paperSeg" role="group" aria-label="Paper size">
|
||
<button data-paper="letter" aria-pressed="true">Letter<br><span style="font-weight:400;font-size:11px;">8.5 × 11 in</span></button>
|
||
<button data-paper="a4" aria-pressed="false">A4<br><span style="font-weight:400;font-size:11px;">210 × 297 mm</span></button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<span class="lbl">Card style</span>
|
||
<div class="seg" id="styleSeg" role="group" aria-label="Card style">
|
||
<button data-style="quarter" aria-pressed="true">Quarter-fold<br>(small)</button>
|
||
<button data-style="flat" aria-pressed="false">Flat ×4</button>
|
||
</div>
|
||
<div class="note" id="styleNote" style="margin-top:10px;">
|
||
<b>Quarter-fold:</b> one portrait sheet, folded twice, makes a small card — front, back, and message all on one sheet.
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<span class="lbl">Theme</span>
|
||
<div class="swatches" id="swatches"></div>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<span class="lbl">Typography</span>
|
||
<div class="field">
|
||
<label for="fFont">Font</label>
|
||
<select id="fFont" style="width:100%;font:inherit;font-size:14px;padding:8px;border-radius:8px;border:1px solid var(--line);background:#fcfbf8;">
|
||
<option value="">(Theme default)</option>
|
||
<optgroup label="Serif (Elegant)">
|
||
<option value="'Playfair Display', serif">Playfair Display</option>
|
||
<option value="'Lora', serif">Lora</option>
|
||
<option value="'Cinzel', serif">Cinzel (Classical)</option>
|
||
</optgroup>
|
||
<optgroup label="Sans-Serif (Modern)">
|
||
<option value="'Montserrat', sans-serif">Montserrat</option>
|
||
<option value="'Raleway', sans-serif">Raleway</option>
|
||
<option value="'Quicksand', sans-serif">Quicksand (Soft)</option>
|
||
</optgroup>
|
||
<optgroup label="Script & Handwritten">
|
||
<option value="'Dancing Script', cursive">Dancing Script</option>
|
||
<option value="'Pacifico', cursive">Pacifico</option>
|
||
<option value="'Caveat', cursive">Caveat</option>
|
||
</optgroup>
|
||
<optgroup label="Playful">
|
||
<option value="'Fredoka', sans-serif">Fredoka</option>
|
||
</optgroup>
|
||
<optgroup label="Pixel & Retro">
|
||
<option value="'Press Start 2P', monospace">Press Start 2P</option>
|
||
</optgroup>
|
||
</select>
|
||
</div>
|
||
<div class="field">
|
||
<label>Alignment</label>
|
||
<div class="seg" id="alignSeg" role="group" aria-label="Text alignment">
|
||
<button data-align="left">Left</button>
|
||
<button data-align="center" aria-pressed="true">Center</button>
|
||
<button data-align="right">Right</button>
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label for="fTitleScale">Title size <span class="slider-val" id="fTitleScaleVal">100%</span></label>
|
||
<input type="range" id="fTitleScale" min="50" max="200" step="5" value="100">
|
||
</div>
|
||
<div class="field" style="margin-bottom:0">
|
||
<label for="fBodyScale">Body size <span class="slider-val" id="fBodyScaleVal">100%</span></label>
|
||
<input type="range" id="fBodyScale" min="50" max="200" step="5" value="100">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group" style="margin-bottom:0">
|
||
<span class="lbl">Colors</span>
|
||
<div class="colorrow">
|
||
<label class="ci">Accent <input type="color" id="cAccent"></label>
|
||
<label class="ci">Text <input type="color" id="cText"></label>
|
||
<label class="ci">Background <input type="color" id="cBg"></label>
|
||
<button class="reset-link" id="resetColors" type="button">Reset to theme</button>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /design -->
|
||
|
||
<!-- ── Text ───────────────────────────────────────── -->
|
||
<div class="tab-panel" data-tab="text">
|
||
|
||
<div class="group">
|
||
<span class="lbl">Quick start</span>
|
||
<div class="presets" id="presets"></div>
|
||
</div>
|
||
|
||
<div class="group" style="margin-bottom:0">
|
||
<span class="lbl">Text</span>
|
||
<div class="field">
|
||
<label for="fTitle">Front title</label>
|
||
<input id="fTitle" type="text" maxlength="60" value="Happy Birthday">
|
||
</div>
|
||
<div class="field">
|
||
<label for="fSub">Front subtitle</label>
|
||
<input id="fSub" type="text" maxlength="80" value="Wishing you a wonderful day">
|
||
</div>
|
||
<div class="field">
|
||
<label for="fMsg" id="msgLabel">Message</label>
|
||
<textarea id="fMsg" maxlength="400">Hope your day is filled with joy, laughter, and a little extra cake.
|
||
|
||
With love,</textarea>
|
||
<div class="hint" id="msgHint">Printed inside the quarter-fold card, or on each flat card.</div>
|
||
</div>
|
||
<div class="field" id="msgSideWrap">
|
||
<label>Message page</label>
|
||
<div class="seg" id="msgSideSeg" role="group" aria-label="Message page">
|
||
<button data-msgside="left">Left page</button>
|
||
<button data-msgside="right" aria-pressed="true">Right page</button>
|
||
</div>
|
||
</div>
|
||
<div class="field" style="margin-bottom:0">
|
||
<label for="fBack">Back footer <span style="color:var(--muted);font-weight:400;">(optional)</span></label>
|
||
<input id="fBack" type="text" maxlength="50" value="">
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /text -->
|
||
|
||
<!-- ── Options ────────────────────────────────────── -->
|
||
<div class="tab-panel" data-tab="options">
|
||
|
||
<div class="group">
|
||
<span class="lbl">Branding</span>
|
||
<label class="opt">
|
||
<input type="checkbox" id="cLogo" checked>
|
||
<span>Include the Beach Party Balloons logo
|
||
<span class="sub">Loads from beachpartyballoons.com — needs internet.</span>
|
||
</span>
|
||
</label>
|
||
<div id="logoPosWrap">
|
||
<span class="lbl" style="margin-bottom:6px;">Logo position</span>
|
||
<div class="seg" id="logoSeg" role="group" aria-label="Logo position">
|
||
<button data-pos="back" aria-pressed="true">Back</button>
|
||
<button data-pos="front" aria-pressed="false">Front</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<span class="lbl">Print guides</span>
|
||
<label class="opt">
|
||
<input type="checkbox" id="cGuide" checked>
|
||
<span id="guideOptLabel">Show fold lines when printing
|
||
<span class="sub" id="guideOptSub">A faint dashed crease to fold against.</span>
|
||
</span>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="note" style="margin-bottom:0">
|
||
<b>Printing tips.</b> In the print dialog set margins to <b>None</b> and enable <b>Background graphics</b> so colors show. Match the paper size in your print dialog to the Design tab selection.
|
||
</div>
|
||
|
||
<!-- kept in DOM for JS compatibility, never visible -->
|
||
<div id="optGroup" style="display:none"><input type="checkbox" id="cInside"></div>
|
||
<div id="printGroup" style="display:none">
|
||
<input type="checkbox" id="cDouble">
|
||
<div id="sideSelector"><div class="seg" id="sideSeg"><button data-side="outside" aria-pressed="true">Outside</button><button data-side="inside" aria-pressed="false">Inside</button></div></div>
|
||
</div>
|
||
|
||
</div><!-- /options -->
|
||
|
||
</aside>
|
||
|
||
<div class="previewOuter">
|
||
<div class="previewWrap" id="previewWrap">
|
||
<div id="sheets"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="script.js"></script>
|
||
|
||
</body>
|
||
</html>
|