/* Base — resets, layout shell (sidebar/workspace), buttons, form fields, panels, tabs, toast */
/* Self-hosted variable Inter (Latin) for the app's own chrome — works fully
   offline once cached by the service worker, unlike a Google Fonts <link>.
   Non-Latin scripts silently fall back to the system font stack below;
   this only affects editor UI text, never the invoice document itself
   (each invoice template sets its own font independently). */
@font-face{font-family:"Inter";src:url("../fonts/inter-variable.woff2") format("woff2-variations"),url("../fonts/inter-variable.woff2") format("woff2");font-weight:100 900;font-style:normal;font-display:swap}
/* Inter (above) doesn't include every currency symbol glyph (₹ ₩ ₪ ₦ ₴ ₺ ₽
   ₱ ₫ ₵ ł č ฿ ৳ are all missing from it) — these three tiny, self-hosted
   subset fonts fill in exactly those characters so currency symbols
   (js/format.js's CURRENCY_SYMBOLS) render correctly even fully offline,
   instead of falling back to tofu boxes or a system font that may not be
   installed. Each is restricted via unicode-range to only the handful of
   codepoints it actually contains, so the browser loads it only when one of
   those specific characters is used. See fonts/LICENSE-CurrencySymbols.txt. */
@font-face{font-family:"Inter";src:url("../fonts/currency-latinext.woff2") format("woff2");font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+20A6,U+20A9,U+20AA,U+20AB,U+20B1,U+20B4,U+20B5,U+20B9,U+20BA,U+20BD,U+0142,U+010D}
@font-face{font-family:"Inter";src:url("../fonts/currency-thai.woff2") format("woff2");font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+0E3F}
@font-face{font-family:"Inter";src:url("../fonts/currency-bengali.woff2") format("woff2");font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+09F3}
/* --app-accent is the app's OWN UI color (tabs, primary buttons, focus rings,
   switches, badges) — fixed, independent of --accent which is set on #invoice
   and only affects the invoice design itself. Changing the invoice's Accent
   color must never restyle the editor chrome. */
:root{--app-accent:#4f46e5;--app-accent-rgb:79,70,229;--app-accent-dark:#4338ca;--accent:#18181b;--accent-rgb:24,24,27;--ink:#1a1d29;--font-modern:"Inter","Segoe UI",Arial,sans-serif;--muted:#6b7280;--line:#e3e6ee;--panel:#fff;--danger:#b42318;--radius:14px;--radius-sm:9px;--sidebar-width:300px;--right-sidebar-width:272px;--page-w:210mm;--page-h:297mm;--shadow-sm:0 1px 2px rgba(16,24,40,.06);--shadow-md:0 6px 20px rgba(16,24,40,.08);--shadow-lg:0 18px 40px rgba(16,24,40,.14);--bg:#eef0f6}
*{box-sizing:border-box;-webkit-print-color-adjust:exact;print-color-adjust:exact;color-adjust:exact}
body{margin:0;font-family:var(--font-modern);background:radial-gradient(1100px 620px at 14% -8%,#eef1fb 0%,var(--bg) 46%) fixed,var(--bg);color:var(--ink);padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
button,input,select,textarea{font:inherit}button{cursor:pointer}
button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid rgba(var(--app-accent-rgb),.25);outline-offset:2px}
.app{display:grid;grid-template-columns:var(--sidebar-width) minmax(0,1fr) var(--right-sidebar-width);min-height:100vh;position:relative}
.sidebar{height:100vh;overflow:auto;position:sticky;top:0;background:#fff;border-right:1px solid var(--line);padding:16px;transition:padding .18s ease}
.sidebar-resizer{position:absolute;top:0;left:var(--sidebar-width);width:6px;height:100%;margin-left:-3px;cursor:col-resize;z-index:16;background:transparent;transition:background .15s}
.sidebar-resizer:hover,.sidebar-resizer.dragging{background:rgba(var(--app-accent-rgb),.35)}
.workspace{padding:18px 20px;overflow:auto}.topbar{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:12px}
/* Right Sidebar — canvas/document settings (Page setup, Alignment, Template,
   Currency). Same visual language as the left .sidebar (panels, fields,
   scroll), mirrored on the opposite edge; independently scrollable so a
   long left sidebar and a short right one (or vice versa) never fight each
   other for space. Hidden entirely at print (css/print.css) and on the
   mobile "Form" view (css/responsive.css) — it's an editing tool, not part
   of the document. */
.right-sidebar{height:100vh;overflow:auto;position:sticky;top:0;background:#fff;border-left:1px solid var(--line);padding:16px}
.appheader{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;background:#fff;border-bottom:1px solid var(--line);padding:10px 16px}
.appheader .topbar{margin-bottom:0;flex:1 1 auto;min-width:0}
.brand{display:flex;gap:10px;align-items:center}.mark{width:38px;height:38px;border-radius:11px;background:linear-gradient(145deg,var(--app-accent),#7c74f0);box-shadow:0 4px 12px rgba(var(--app-accent-rgb),.35);color:#fff;font-weight:900;display:grid;place-items:center;flex:none}
.brand h1{font-size:17px;margin:0;letter-spacing:-.01em}.brand p{margin:2px 0 0;font-size:11px;color:var(--muted)}
.actions{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}.btn{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:#fff;border-radius:var(--radius-sm);padding:7px 11px;font-size:12px;font-weight:750;color:var(--ink);box-shadow:var(--shadow-sm);transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease,background-color .12s ease}
.actions-more{display:contents}.actions-more-toggle{display:none}
.mtb-icon,.drawer-overlay,.mobile-drawer,.fullscreen-exit{display:none}
.btn:hover{border-color:#c2c9d6;transform:translateY(-1px);box-shadow:var(--shadow-md)}.btn:active{transform:translateY(0)}.btn.primary{background:linear-gradient(160deg,var(--app-accent),var(--app-accent-dark));border-color:var(--app-accent-dark);color:#fff}.btn.primary:hover{box-shadow:0 10px 22px rgba(var(--app-accent-rgb),.32)}.btn.danger{color:var(--danger)}.btn.small{padding:6px 9px;font-size:11px}.btn.icon{width:31px;height:31px;padding:0}
.tabs{display:grid;grid-template-columns:repeat(4,1fr);gap:4px;background:#eef0f7;padding:4px;border-radius:11px;margin-bottom:10px}.tab{border:0;background:transparent;border-radius:8px;padding:7px 2px;font-size:9.5px;font-weight:800;line-height:1.25;color:#5c6472;transition:background-color .15s ease,color .15s ease}.tab.active{background:#fff;box-shadow:var(--shadow-sm);color:var(--app-accent)}
.tabpane{display:none}.tabpane.active{display:block}
.panel{border:1px solid var(--line);border-radius:var(--radius);padding:12px;margin-bottom:10px;background:var(--panel);box-shadow:var(--shadow-sm);transition:box-shadow .15s ease}
.panelhead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px;cursor:pointer;user-select:none}
.panelhead h2{font-size:13px;margin:0;letter-spacing:-.005em}.hint{font-size:10px;color:var(--muted)}
.panelhead::after{content:"⌄";margin-left:6px;color:var(--muted);font-size:13px;transition:transform .15s ease;flex:none}
.panel.collapsed{padding-bottom:12px}.panel.collapsed>*:not(.panelhead){display:none}.panel.collapsed .panelhead{margin-bottom:0}.panel.collapsed .panelhead::after{transform:rotate(-90deg)}
.grid2,.grid3{display:grid;gap:8px}.grid2{grid-template-columns:1fr 1fr}.grid3{grid-template-columns:repeat(3,1fr)}.full{grid-column:1/-1}
.field label{display:block;font-size:10.5px;font-weight:850;text-transform:uppercase;letter-spacing:.04em;color:#475467;margin-bottom:3px}.field input,.field select,.field textarea{width:100%;border:1px solid #d7dce5;border-radius:var(--radius-sm);padding:7px 9px;background:#fff;min-height:34px;transition:border-color .12s ease,box-shadow .12s ease}.field input:focus,.field select:focus,.field textarea:focus{border-color:rgba(var(--app-accent-rgb),.55);box-shadow:0 0 0 3px rgba(var(--app-accent-rgb),.12)}.field textarea{min-height:60px;resize:vertical}
.field .colorrow{display:flex;gap:6px;align-items:center}.field .colorrow input[type=color]{width:40px;padding:2px;flex:none;min-height:34px}.field .colorrow input[type=text]{flex:1}
.toggleline{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:8px 0;border-bottom:1px dashed #e0e5ec;font-size:12px}.toggleline:last-child{border-bottom:0}.switch{position:relative;width:38px;height:21px}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;inset:0;background:#c9d1dc;border-radius:20px;transition:.2s}.slider:before{content:"";position:absolute;width:15px;height:15px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.2s;box-shadow:0 1px 3px rgba(16,24,40,.25)}.switch input:checked+.slider{background:var(--app-accent)}.switch input:checked+.slider:before{transform:translateX(17px)}
.columnrow{border:1px solid #dde3eb;border-radius:var(--radius-sm);padding:9px;margin-bottom:7px;background:#fbfcfe}.columnhead{display:flex;align-items:center;gap:6px;margin-bottom:7px}.drag{color:#7a8390;cursor:grab;font-size:17px}.columnhead strong{font-size:11px;flex:1}.colgrid{display:grid;grid-template-columns:1.2fr .8fr .6fr;gap:7px}.tiny{font-size:10px}
.itemcard{border:1px solid #dde3eb;border-radius:var(--radius-sm);padding:9px;margin-bottom:7px;background:#fbfcfe}.itemtop{display:flex;justify-content:space-between;align-items:center;margin-bottom:7px}.itemtop strong{font-size:11px}.itemgrid{display:grid;gap:7px;grid-template-columns:repeat(2,1fr)}.itemgrid .field textarea{min-height:44px}
.historycard{border:1px solid #dde3eb;border-radius:10px;padding:10px;margin-bottom:8px;background:#fbfcfe}.historycard.current{border-color:var(--app-accent);box-shadow:0 0 0 1px rgba(var(--app-accent-rgb),.25)}.historytop{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.historytop strong{font-size:12.5px}.historyamount{font-size:12.5px;font-weight:800;white-space:nowrap}.historymeta{display:flex;justify-content:space-between;align-items:center;margin:6px 0 8px;gap:8px}.historyactions{display:flex;gap:6px;flex-wrap:wrap}.historyactions .btn{flex:1 1 auto}
.tinybadge{font-size:8.5px;font-weight:800;color:var(--app-accent);background:rgba(var(--app-accent-rgb),.1);border-radius:6px;padding:2px 6px;margin-left:5px;text-transform:uppercase;letter-spacing:.04em;vertical-align:middle}
.install-banner{display:flex;align-items:center;justify-content:space-between;gap:10px;background:rgba(var(--app-accent-rgb),.06);border:1px solid rgba(var(--app-accent-rgb),.16);border-radius:10px;padding:9px 10px;margin-bottom:10px;font-size:11.5px;line-height:1.35}
@media (min-width:641px){.install-banner{display:none!important}}
.notice{font-size:11px;color:#475467;background:rgba(var(--app-accent-rgb),.07);border:1px solid rgba(var(--app-accent-rgb),.14);padding:8px 9px;border-radius:9px;margin-bottom:10px}
.importhelp{margin:8px 0 10px;font-size:11.5px}
.importhelp summary{cursor:pointer;font-weight:800;color:var(--app-accent);list-style:none;padding:2px 0}
.importhelp summary::-webkit-details-marker{display:none}
/* Bounded, independently-scrolling tutorial body — max-height + overflow-y
   keep it (and the rest of the Import panel below it: the danger zone) on
   screen and reachable even on a short window, instead of the accordion
   pushing the whole floating panel past the bottom of the viewport with no
   way to scroll the overflow into view. overscroll-behavior:contain stops
   scrolling this inner box from also scrolling the panel/page behind it
   once it hits its own top/bottom edge. */
.importhelp-body{margin-top:8px;padding:8px 10px;background:#f7f9fc;border:1px solid #e1e6ee;border-radius:9px;color:#344054;line-height:1.45;max-height:min(220px,40vh);overflow-y:auto;overscroll-behavior:contain}
.importhelp-body p{margin:0 0 6px;font-size:11px}
.importhelp-body p:last-child{margin-bottom:0}
.importhelp-list{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:5px}
.importhelp-list li{font-size:11px}
.importhelp-list strong{color:var(--ink)}
.importhelp-aliases{display:block;color:var(--muted);font-size:10.5px;margin-top:1px}
.importhelp-body a{color:var(--app-accent);font-weight:700;text-decoration:none}
.importhelp-body a:hover{text-decoration:underline}
/* Visually separates an irreversible action (Clear all line items) from the
   ordinary actions above it inside a dropdown panel — a dashed rule + small
   uppercase "Danger zone" label, the same convention modern SaaS settings
   pages use to make sure a destructive action is never mistaken for a
   routine one. The button itself still requires a confirm() before anything
   is actually deleted. */
.danger-zone{margin-top:10px;padding-top:10px;border-top:1px dashed #f0d3ce}
.danger-zone-label{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--danger);margin-bottom:6px}
/* Sprite icons — replace pictographic emoji so every icon renders identically
   across platforms and can inherit the surrounding text color (including the
   app accent), instead of relying on the OS's own colorful emoji font. */
.icon{width:15px;height:15px;flex:none;stroke:currentColor;vertical-align:-2px}
.btn .icon{margin-right:5px}
.btn.icon .icon{margin-right:0}
.drawer-item{gap:10px}
.drawer-item .icon{width:17px;height:17px}
.canvasmode-btn .icon{width:14px;height:14px}
.install-banner .icon{width:15px;height:15px;margin-right:5px;vertical-align:-3px;color:var(--app-accent)}
.hidden{display:none!important}
.toast{position:fixed;right:20px;bottom:20px;background:#191d2b;color:#fff;padding:11px 14px;border-radius:11px;box-shadow:var(--shadow-lg);font-size:12.5px;max-width:min(360px,calc(100vw - 40px));opacity:0;transform:translateY(8px);pointer-events:none;transition:.2s;z-index:99}
.toast.show{opacity:1;transform:none}
@media (max-width:640px){.toast{left:14px;right:14px;bottom:calc(74px + env(safe-area-inset-bottom));max-width:none;text-align:center}
  body.fullscreen-preview .toast{bottom:calc(14px + env(safe-area-inset-bottom))}}

/* Invoice toolbar — Save/Duplicate/History/New invoice. Shares one visual
   pill with the Edit/Preview + Zoom bar on desktop (see .toolbar-row in
   css/invoice.css, which supplies the shared background/border/shadow)
   instead of stacking as two separate boxed bars; on phones this becomes a
   plain vertical list once js/layout.js moves it into the hamburger
   drawer (see .drawer-toolbar-slot in responsive.css for that styling). */
.invoice-toolbar{display:flex;justify-content:center}
.invoice-toolbar-actions{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}
/* Tiny "Saved ✓ 4:12 PM" confirmation that appears next to Save right after
   it succeeds and fades after a few seconds — a persistent, easy-to-spot
   confirmation (unlike the toast, which is easy to miss) that the click
   actually did something, addressing "it doesn't look like it's saving". */
.save-status{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;color:#18794e;opacity:0;transform:translateX(-4px);transition:opacity .2s ease,transform .2s ease;white-space:nowrap}
.save-status.show{opacity:1;transform:translateX(0)}
.history-dropdown{position:relative}
/* Positioned as position:fixed with top/left set inline by JS (see
   layout.js's positionDropdownPanel) rather than position:absolute here —
   .toolbar-row (the button strip these dropdowns hang off of) has
   overflow-x:auto for horizontal scrolling on narrow widths, and any
   absolutely-positioned descendant gets clipped to that scrolling
   container's own bounds, which was squashing this panel visually inside
   the toolbar instead of letting it float below it. Fixed positioning
   with JS-computed coordinates escapes that clipping entirely. The mobile
   media query below still overrides this into simple centered-fixed. */
/* #floatingLayer (end of <body>) holds every one of these panels — see the
   long comment there for why they can't live inside the buttons/toolbars
   that open them. z-index:100 clears every other layer in the app (toast
   99, fullscreen-exit 60, mobile drawer 50) so a panel is never hidden
   behind app chrome regardless of viewport width. */
#floatingLayer{position:relative;z-index:100}
.history-panel{display:none;position:fixed;z-index:100;width:min(360px,calc(100vw - 32px));max-height:70vh;overflow:auto;background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-lg);padding:12px}
.history-panel.open{display:block}
.history-panel-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.history-panel-head h2{font-size:13px;margin:0}

/* Off-screen but still fully functional data-backing fields (see
   #detailsHiddenFields in index.html) — every value on the invoice that
   isn't shown as its own sidebar panel anymore, now that it's directly
   editable in the live preview instead. Uses the standard "visually
   hidden" clip pattern (not display:none) so the hidden file input can
   still be opened programmatically (logobox click / drag-drop) and the
   range slider can still be dragged via the on-canvas resize handle. */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

