<template>
  <v-dialog :model-value="modelValue" max-width="1180" scrollable @update:model-value="$emit('update:modelValue', $event)">
    <v-card class="user-manual-print" height="90vh">
      <v-toolbar color="primary" density="comfortable" class="px-2">
        <v-icon icon="mdi-book-open-page-variant" class="ml-2 mr-2" />
        <v-toolbar-title class="font-weight-bold">DepreCore User Guide</v-toolbar-title>
        <v-spacer />
        <v-btn variant="text" prepend-icon="mdi-printer" class="d-print-none" @click="print">Print / Save PDF</v-btn>
        <v-btn icon="mdi-close" variant="text" class="d-print-none" @click="$emit('update:modelValue', false)" />
      </v-toolbar>

      <div class="manual-body">
        <!-- Section navigation -->
        <nav class="user-manual-nav">
          <v-text-field
            v-model="search"
            density="compact"
            hide-details
            clearable
            variant="solo-filled"
            flat
            placeholder="Search topics"
            prepend-inner-icon="mdi-magnify"
            class="ma-2"
          />
          <v-list density="compact" nav class="pa-1">
            <v-list-item
              v-for="section in filteredSections"
              :key="section.id"
              :active="active === section.id"
              :prepend-icon="section.icon"
              :title="section.title"
              rounded="sm"
              @click="select(section.id)"
            />
            <v-list-item v-if="!filteredSections.length" class="quiet text-body-2">No topics match “{{ search }}”.</v-list-item>
          </v-list>
        </nav>

        <!-- Content -->
        <div ref="content" class="manual-content user-manual-content">
          <div class="manual-doc-title d-none d-print-block">
            <h1>DepreCore User Guide</h1>
            <p class="quiet">Fixed-asset management, depreciation, maintenance &amp; integrations</p>
          </div>

          <!-- GETTING STARTED -->
          <section v-show="isShown('overview')" class="manual-section">
            <h2>Getting started</h2>
            <p>
              DepreCore is an integrated system for tracking physical assets through their full lifecycle —
              acquisition, depreciation across multiple accounting books, preventative maintenance, disposal — alongside
              a parts inventory, a contacts/CRM directory, an alerting engine, and connectors to email, webhooks, and ServiceNow.
            </p>
            <p>Most day-to-day work follows one of these flows:</p>
            <ul>
              <li><strong>Record an asset</strong> → set its books &amp; depreciation → attach warranties, files, photos, and maintenance plans.</li>
              <li><strong>Maintain it</strong> → complete preventative-maintenance services, log tasks and notes, draw down spare parts.</li>
              <li><strong>Account for it</strong> → review the general ledger per book, run reports, and record disposals or impairments when it leaves service.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              You can reopen this guide at any time from the <strong>?</strong> icon in the top bar. Use the topic list on the
              left, or the search box, to jump to a subject. The <strong>Print / Save PDF</strong> button produces a complete printable manual.
            </v-alert>
            <h3>Signing in</h3>
            <p>
              Sign in with your email and password. Your <em>role</em> determines which screens and actions are available
              (see <a href="#" @click.prevent="select('roles')">Roles &amp; permissions</a>). If a screen is missing from your
              left-hand menu, your role does not grant access to it.
            </p>
          </section>

          <!-- INTERFACE -->
          <section v-show="isShown('navigation')" class="manual-section">
            <h2>Interface &amp; navigation</h2>
            <h3>The left navigation rail</h3>
            <p>
              The rail on the left lists every screen your role can access. Some items expand to reveal sub-items:
              <strong>Assets</strong> contains <strong>Scan</strong>, <strong>Assignments</strong>, and <strong>Templates</strong>; <strong>Maintenance</strong>
              contains <strong>Parts inventory</strong>; and <strong>Financial</strong> contains <strong>Books</strong> and <strong>Tax rules</strong>.
              <strong>Admin</strong> expands to <strong>Users &amp; Teams</strong>, <strong>Application Configuration</strong>, and <strong>Integrations</strong>.
              Collapse the rail to icons using the chevron at the top of the rail
              (or the menu button in the top bar) to give content more room; your choice is remembered on this device.
            </p>
            <h3>The top bar</h3>
            <ul>
              <li>Shows the current screen title and a short description.</li>
              <li>Screen-specific actions (such as <strong>New asset</strong>) appear on the right.</li>
              <li>The <strong>?</strong> icon opens this user guide.</li>
              <li>Your avatar opens the profile menu for theme selection and sign-out.</li>
            </ul>
            <h3>Themes &amp; appearance</h3>
            <p>
              Open the profile menu (your avatar, top-right) to personalize the interface. All choices are saved to your account and
              follow you between devices:
            </p>
            <ul>
              <li><strong>Theme</strong> — several dark options (Dark, Ocean, Slate, High contrast) and light options (Light, Sepia).</li>
              <li><strong>Text size</strong> — Small, Normal, Large, or Extra large; this scales the whole interface for easier reading.</li>
              <li><strong>Accent colour</strong> — pick a preset swatch or enter any custom hex value; choose “default” to return to the theme’s colour. Button text automatically switches to black or white for legibility.</li>
              <li><strong>High-contrast boost</strong> — strengthens borders, text, and link underlines on top of whichever theme you’re using.</li>
            </ul>

            <h3>Accessibility</h3>
            <p>DepreCore is built to work with assistive technology:</p>
            <ul>
              <li>Press <strong>Tab</strong> to reveal a “Skip to main content” link, and to move through controls with a clear keyboard focus outline.</li>
              <li>Images and photos carry descriptive text for screen readers, and icon-only buttons have spoken labels.</li>
              <li>The text-size and high-contrast options above support low-vision use, and the app honours your system’s “reduce motion” setting.</li>
            </ul>
            <h3>Tables</h3>
            <p>Most lists use a consistent table with the same controls everywhere:</p>
            <ul>
              <li><strong>Filter box</strong> — type to narrow the rows.</li>
              <li><strong>Sortable columns</strong> — click a header to sort; click again to reverse, a third time to clear.</li>
              <li><strong>Rows per page</strong> and pagination at the bottom; choose <em>All</em> to show everything.</li>
              <li>Headers stay visible (sticky) while you scroll long lists.</li>
            </ul>
          </section>

          <!-- DASHBOARD -->
          <section v-show="isShown('dashboard')" class="manual-section">
            <h2>Dashboard</h2>
            <p>
              The Dashboard is your portfolio at a glance. It summarizes the number of assets, total cost, how many are in
              service versus disposed, and a chart of value by category, with a supporting breakdown table beneath it.
              It also surfaces recent activity and upcoming work so you can see what needs attention without opening each screen.
            </p>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              The Dashboard is read-only — it is a reporting surface. Make changes from the relevant screen (Assets, Maintenance, etc.)
              and the Dashboard updates automatically.
            </v-alert>
          </section>

          <!-- ASSETS -->
          <section v-show="isShown('assets')" class="manual-section">
            <h2>Assets — creating &amp; managing</h2>
            <p>
              The <strong>Asset register</strong> lists every asset. Use the filter and status selector to find records, select
              rows for bulk actions, and open any asset to edit it in the <em>asset workbench</em> (the panel that slides in from the right).
            </p>

            <h3>Creating an asset</h3>
            <ol>
              <li>Click <strong>New asset</strong> in the top bar.</li>
              <li>Optionally pick a <strong>Template</strong> to pre-fill category, life, method, GL accounts, and custom fields.</li>
              <li>Fill in the <strong>Details</strong>: description, category, acquisition cost, acquired / in-service dates, useful life, location, custodian, serial number, and so on.</li>
              <li>Click <strong>Save asset</strong>. The workbench stays open on the new record so you can immediately add books, files, photos, warranties, and maintenance.</li>
            </ol>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              An Asset ID is generated automatically if you leave it blank. You can also type your own identifier.
            </v-alert>

            <h3>The asset workbench tabs</h3>
            <table class="manual-table">
              <thead><tr><th>Tab</th><th>What it’s for</th></tr></thead>
              <tbody>
                <tr><td><strong>Details</strong></td><td>Core asset data, GL accounts, condition, and the barcode label (print a single label here).</td></tr>
                <tr><td><strong>Books</strong></td><td>Per-book depreciation settings — each book can carry its own cost, method, life, §179, bonus, and convention. See <a href="#" @click.prevent="select('books')">Books, depreciation &amp; tax</a>.</td></tr>
                <tr><td><strong>Files</strong></td><td>Attach invoices, manuals, and insurance records. Files are stored with the asset and can be downloaded later.</td></tr>
                <tr><td><strong>Photos</strong></td><td>Identification photos — what the asset looks like, where it is, nameplates and serial labels. Each photo can have a caption. On a phone, <strong>Add photos</strong> opens the camera.</td></tr>
                <tr><td><strong>Warranties</strong></td><td>Provider, coverage window, limits, and details. Expiring warranties raise alerts.</td></tr>
                <tr><td><strong>Tasks</strong></td><td>Ad-hoc to-dos (inspection, calibration, renewal). Overdue tasks raise alerts. Tick a task to complete it.</td></tr>
                <tr><td><strong>Notes</strong></td><td>A running, timestamped log of comments about the asset.</td></tr>
                <tr><td><strong>Disposal</strong></td><td>Record a sale/retirement and impairments — see <a href="#" @click.prevent="select('lifecycle')">Asset lifecycle</a>.</td></tr>
                <tr><td><strong>Lease</strong></td><td>Capture lease terms and view the amortization schedule — see <a href="#" @click.prevent="select('lifecycle')">Asset lifecycle</a>.</td></tr>
                <tr><td><strong>PM</strong></td><td>Attach preventative-maintenance plans and complete services — see <a href="#" @click.prevent="select('pm')">Preventative maintenance</a>.</td></tr>
              </tbody>
            </table>

            <h3>Editing &amp; bulk changes</h3>
            <ul>
              <li>Open any row to edit it, then <strong>Save asset</strong>.</li>
              <li>Select multiple rows and use <strong>mass edit</strong> to change status, location, or department across all of them at once.</li>
              <li><strong>Import</strong> a spreadsheet to create/update many assets, and <strong>export</strong> the register to a file.</li>
            </ul>

            <h3>Status values</h3>
            <p>
              Assets move through statuses such as <em>in service</em>, <em>CIP</em> (construction in progress), <em>reserved</em>,
              <em>checked out</em>, <em>disposed</em>, and <em>retired</em>. Status drives filtering, the Dashboard counts, and which
              records appear in reports.
            </p>
          </section>

          <!-- LIFECYCLE -->
          <section v-show="isShown('lifecycle')" class="manual-section">
            <h2>Asset lifecycle — disposal, leases &amp; impairment</h2>

            <h3>Disposing of an asset</h3>
            <p>Open the asset, go to the <strong>Disposal</strong> tab, and:</p>
            <ol>
              <li>Choose the <strong>book</strong> the disposal is calculated against, the <strong>disposal type</strong> (sale, exchange, abandonment, like-kind, involuntary conversion), and the date.</li>
              <li>Enter the sale price and any selling expense. For a partial disposal, tick <strong>Partial</strong> and enter the cost basis being removed.</li>
              <li>Click <strong>Calculate gain/loss</strong> to preview accumulated depreciation, net book value, proceeds, and the resulting gain or loss.</li>
              <li>Click <strong>Record disposal</strong> to finalize. The asset is marked disposed and the entry appears in the disposal history (you can reverse it from there if needed).</li>
            </ol>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Gain/loss is computed from the selected book’s net book value at the disposal date, so the figure reflects that book’s
              method and conventions. Disposals also feed the disposal and gain/loss reports.
            </v-alert>

            <h3>Impairments &amp; adjustments</h3>
            <p>
              Below the disposal form, record an <strong>impairment</strong>, write-down, write-up, or revaluation against a specific
              book with an amount, date, and reason. These adjust the asset’s carrying value and appear in the adjustments report.
            </p>

            <h3>Leases</h3>
            <p>
              On the <strong>Lease</strong> tab, capture the lessor, total contract value, start/end dates, discount rate, and payment
              frequency. Select a saved lease to view its <strong>amortization schedule</strong> — present value (right-of-use asset),
              periodic payment, and the period-by-period split of interest, principal, and remaining liability. Leases nearing their
              end date raise alerts.
            </p>
          </section>

          <!-- BARCODES -->
          <section v-show="isShown('barcodes')" class="manual-section">
            <h2>Barcodes &amp; scanning</h2>
            <h3>Printing labels</h3>
            <p>
              Every asset can carry a barcode value (it falls back to the Asset ID if left blank). Print a single label from the
              asset’s <strong>Details</strong> tab, or select multiple assets in the register and print a <strong>label sheet</strong> for batch tagging.
            </p>
            <h3>The Scan screen</h3>
            <p>
              Use <strong>Scan</strong> to find an asset in the field: point your device camera at a barcode (or type the code), and the
              matching asset opens so you can update its status, location, department, custodian, and condition, or add a quick note on the spot.
            </p>
            <v-alert type="warning" variant="tonal" density="comfortable" class="manual-callout">
              Camera scanning requires a secure (HTTPS) connection or running on the local machine. Where the camera isn’t available,
              manual code entry works everywhere.
            </v-alert>
          </section>

          <!-- BOOKS / DEPRECIATION -->
          <section v-show="isShown('books')" class="manual-section">
            <h2>Books, depreciation &amp; tax</h2>
            <p>
              A <strong>book</strong> is a parallel set of depreciation figures — for example GAAP (financial statements), Federal tax,
              State, AMT, ACE, and your own user-defined books. The same physical asset is depreciated independently in each book, so you
              can satisfy financial reporting and several tax regimes from one record.
            </p>

            <h3>How the financial modules relate to asset tracking</h3>
            <ul>
              <li><strong>Books screen</strong> — defines the <em>registry</em> of books available across the whole system: which are enabled, each book’s default method and convention, and which tax rule set it uses.</li>
              <li><strong>Asset → Books tab</strong> — every enabled book appears here for each asset, where you can override cost, life, method, §179, bonus, and convention <em>per book, per asset</em>.</li>
              <li><strong>Tax rule sets</strong> — supply the catalog of depreciation methods and the statutory limits (e.g. §179 caps, bonus %) that a book draws on. Assigning a rule set to a book is what makes that book follow a given jurisdiction’s rules.</li>
              <li><strong>Depreciation engine</strong> — calculates each book using its assigned rule set; the results drive the general ledger, reports, and disposal gain/loss.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              In short: <em>Tax rule set → assigned to a Book → applied per Asset → produces depreciation → rolls up to the GL and reports.</em>
            </v-alert>

            <h3>Configuring books</h3>
            <p>On the <strong>Books</strong> screen you can:</p>
            <ul>
              <li>Enable/disable books, set each book’s default method and convention, and assign its tax rule set.</li>
              <li><strong>Create a user-defined book</strong> (e.g. IFRS or an internal management book) with the <strong>New book</strong> button. Newly enabled books automatically appear on every asset’s Books tab.</li>
              <li>Delete a book that isn’t a primary or maintenance book and isn’t in use.</li>
            </ul>

            <h3>The general ledger view</h3>
            <p>
              Select a book to view its <strong>GL ledger</strong> in debit/credit format — asset cost, accumulated depreciation, and the
              period’s depreciation expense rolled to GL accounts, with per-asset detail and a summary. You can export the ledger.
              This rollup is computed automatically from depreciation; the <strong>Journal entries</strong> panel below it is a separate,
              editable layer (the two do not double-count).
            </p>

            <h3>GL journal entries — add, edit, import &amp; track changes</h3>
            <p>
              Below the computed ledger, the <strong>Journal entries</strong> panel holds stored, editable GL postings for the selected
              book and year. Use it to record manual journal lines or to load entries from another system.
            </p>
            <ul>
              <li><strong>Add / edit / delete.</strong> Click <strong>Add entry</strong> (or the pencil/trash on a row) to capture a
                date, GL account, account type, description, reference, <strong>debit</strong> and/or <strong>credit</strong>, and an
                optional <strong>external ID</strong>. The panel shows running debit, credit, and balance totals.</li>
              <li><strong>Import (CSV or Excel/XLS).</strong> Click <strong>Import</strong> and choose a <code>.csv</code>,
                <code>.xlsx</code>, or <code>.xls</code> file. Column headers are matched flexibly (Date, Account, Debit, Credit,
                Reference, Description, External&nbsp;Id, …).</li>
              <li><strong>Conflict / merge resolution.</strong> The import first shows a <strong>preview</strong> that classifies every
                row as <em>New</em>, <em>Update</em> (matches an existing entry but differs), <em>Duplicate</em> (identical), or
                <em>Error</em>, with counts. Rows are matched to existing entries by <strong>external ID</strong> first, then by a
                natural key (date + account + debit + credit + reference). You then pick a strategy — <strong>Skip conflicts</strong>,
                <strong>Merge</strong> (update existing + insert new), or <strong>Insert as new</strong> — and confirm. Set an external ID
                on your entries for the most reliable re-import matching.</li>
              <li><strong>Export.</strong> The <strong>Export</strong> menu downloads the current entries as CSV or Excel (XLSX).</li>
              <li><strong>Change history.</strong> Every add, edit, delete, and import is fully logged. Click the <strong>history</strong>
                (clock) icon on a row to see that entry’s timeline — who changed it, when, and a field-level before→after diff. The same
                events are searchable system-wide in <strong>Admin → Activity &amp; Audit Trail</strong>.</li>
            </ul>

            <h3>Depreciation methods &amp; critical fields</h3>
            <p>
              Each book’s depreciation is computed from the depreciation-critical fields: property type, placed-in-service date,
              acquisition value, depreciation method, estimated life, salvage value, Section 168 (bonus) allowance %, Section 179, and
              business-use %. Supported 200% declining-balance methods include <strong>MF200</strong> (MACRS formula),
              <strong>MT200</strong> (MACRS tables), and <strong>MI200</strong> (MACRS, Indian-reservation) — which ignore salvage and
              recover the full basis — and <strong>DB200</strong>, <strong>DH200</strong> (half-year), and <strong>DD200</strong> (full-year),
              which honor salvage (depreciating only down to it). All switch to straight-line when that yields a larger deduction.
            </p>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              When you change a depreciation-critical field on an asset that already has depreciation, a prompt asks <strong>when to apply</strong>
              the change: <em>Placed-in-service date</em> (rebuild the whole schedule) or <em>Current period — going forward</em> (keep depreciation
              already recorded).
            </v-alert>

            <h3>Special depreciation zones</h3>
            <p>
              Assign a <strong>Special depreciation zone</strong> on the asset’s Details tab (e.g. <strong>New York Liberty Zone</strong>) and the
              engine automatically applies the zone’s §168 special allowance (30% for NY Liberty) to the <strong>federal book</strong> when the
              asset’s placed-in-service date falls within the zone’s window. The form shows a note confirming the allowance, the date window,
              and any leasehold-improvement life. Zones are managed in <strong>Admin → Application Configuration → Depreciation zones</strong>
              (create your own, set the allowance %, date window, and notes).
            </p>
            <p>
              A zone can instead (or also) carry an <strong>increased §179 limit</strong> — this is how
              <strong>Enterprise / Empowerment Zone</strong> property is handled. Set the zone’s <em>§179 limit increase</em>
              (e.g. +$35,000 for 2002–2020) and its <em>§179 cost factor</em> (e.g. 0.5, meaning only 50% of the property’s cost counts
              toward the investment-phaseout threshold). When such a zone is assigned to an asset placed in service within the window,
              the federal book’s §179 deduction may exceed the standard annual limit by that increase. The base annual §179 deduction
              limits and phaseout thresholds themselves are maintained in
              <strong>Admin → Application Configuration → Section 179 limits</strong>; the engine caps each asset’s §179 deduction at the
              applicable year’s limit (less any dollar-for-dollar phaseout). If no limit is configured for an asset’s placed-in-service
              year, the entered §179 amount is left uncapped.
            </p>
            <p>
              A zone can combine both incentives. The seeded <strong>Qualified Gulf Opportunity (GO) Zone</strong> applies a
              <strong>50% §168 allowance</strong> (placed in service 2005–2011) <em>and</em> a <strong>+$100,000 §179 increase</strong>
              (which ends earlier, in 2008) with the phaseout threshold raised by the lesser of $600,000 or the property’s cost. To
              support cases like this, each zone has an optional separate <em>§179 window</em> (so the §179 increase can expire before
              the bonus allowance does) and a <em>§179 threshold-increase cap</em>. Assign the zone on the asset and the engine applies
              each benefit only while the asset’s placed-in-service date is inside that benefit’s own window. Other seeded disaster/relief
              zones follow the same pattern — e.g. the <strong>Qualified Recovery Assistance (Kansas Disaster Zone)</strong> (50% allowance
              + $100,000 §179 increase, placed in service 2007–2008).
            </p>

            <h3>Listed property &amp; passenger automobiles (§280F)</h3>
            <p>
              Two switches on an asset’s Details tab drive the §280F rules (IRS Pub 946):
            </p>
            <ul>
              <li><strong>Listed property</strong> — when such an asset is used <strong>50% or less</strong> for qualified
                business (its <em>Business use %</em>), the engine automatically switches it to <strong>ADS straight-line</strong>
                and disallows §179 and bonus depreciation, exactly as §280F requires. Above 50%, it depreciates normally.</li>
              <li><strong>Passenger automobile</strong> — flags the asset for the annual <strong>luxury-auto depreciation caps</strong>.
                Each year’s depreciation is limited to the §280F cap for the placed-in-service year (the higher first-year figure
                applies when bonus is claimed), reduced by the business-use %. Any basis not recovered within the recovery period
                continues at the final-year cap until the asset is fully depreciated.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              The yearly cap amounts are maintained in <strong>Admin → Application Configuration → §280F passenger-auto limits</strong>
              (indexed annually by the IRS); like the §179 limits, they are editable data — no software update needed when the IRS
              publishes new figures.
            </v-alert>

            <h3>Section 179 limitation &amp; carryover</h3>
            <p>
              While the engine caps <em>each asset’s</em> §179 at the annual dollar limit and investment phase-out, the
              <strong>Financial → Section 179</strong> screen provides the <strong>return-level</strong> view: it totals the §179
              elected across the company’s assets for a tax year and applies the <strong>annual dollar limit</strong> (reduced by the
              phase-out once §179 property cost exceeds the threshold) <em>and</em> your <strong>business taxable-income limit</strong>
              (§179 can’t create a loss). Enter your taxable income, and the worksheet shows the allowed deduction and the
              <strong>carryover</strong> of any disallowed amount. Saving stores the carryover so the <strong>next year automatically
              picks it up</strong> as additional available §179.
            </p>

            <h3>The PM (maintenance) book</h3>
            <p>
              A dedicated <strong>PM book</strong> tracks actual maintenance <em>spend</em> per asset rather than depreciation. Its ledger
              aggregates the cost captured when preventative-maintenance services are completed (see <a href="#" @click.prevent="select('pm')">Preventative maintenance</a>).
            </p>

            <h3>Reports</h3>
            <p>
              The <strong>Reports</strong> screen is catalog-driven: choose a report, set parameters (book, year, etc.), and view a table
              with totals and an optional chart. Reports cover depreciation schedules and expense, net book value, roll-forwards,
              acquisitions, disposals and gain/loss, adjustments, journal entries, several tax forms, and maintenance/PM and alert
              reports. You can save report configurations to rerun later and export results to PDF, Excel, or CSV. To print an individual
              PM plan, run the PM plan report and export it.
            </p>
            <p>The catalog is grouped for audit-grade internal, board, and client reporting:</p>
            <ul>
              <li><strong>Journals &amp; registers</strong> — the <strong>Asset journal</strong> (a full per-asset dossier of financials,
                maintenance history, notes, warranties, adjustments and disposals, with photo thumbnails embedded in the PDF/print
                export), the <strong>Fixed asset journal</strong> (complete register), and GL <strong>journal entries</strong> (debit/credit)
                for monthly depreciation, disposals, revaluations, and write-offs.</li>
              <li><strong>Transactions</strong> — event listings for assets <strong>purchased</strong>, <strong>disposed</strong>,
                <strong>revalued</strong>, and <strong>written off</strong>, each filterable by year and an optional month.</li>
              <li><strong>Summaries</strong> — aggregated by category or method: asset, depreciation, YTD depreciation, purchase,
                disposal, revaluation, and write-off summaries.</li>
              <li><strong>Detail</strong> — <strong>Asset history</strong>, a chronological timeline of every event for one asset
                (acquisition, edits, maintenance, notes, warranties, adjustments, and disposal).</li>
            </ul>
            <p class="quiet text-body-2">
              Reporting conventions: a <strong>“…&nbsp;journal”</strong> is a double-entry GL posting (debits = credits); a
              <strong>“…&nbsp;transaction”</strong> lists the underlying records. <strong>Revaluation</strong> reports cover
              revaluation / write-up / write-down adjustments; <strong>write-off</strong> reports cover impairments plus abandonment
              disposals. <em>Future depreciation calculation</em> is the multi-year projection.
            </p>
          </section>

          <!-- PERIOD CLOSE -->
          <section v-show="isShown('close')" class="manual-section">
            <h2>Period close — month-end &amp; year-end</h2>
            <p>
              <strong>Financial → Period Close</strong> is a guided wizard that walks you through closing an accounting
              period for the fixed-asset subledger. It reviews the period's activity, <strong>posts the journal entries the
              close generates into the general ledger</strong>, reconciles the Fixed Asset Register to the GL, and then
              <strong>locks the period</strong> so it can't be changed after the fact. Every action is recorded in
              <a href="#" @click.prevent="select('admin')">Activity &amp; Audit Trail</a>.
            </p>

            <h3>Scope: which book, which period</h3>
            <ul>
              <li>A close runs against <strong>one book</strong> — pick it at the top of the screen; it defaults to your
                <strong>primary book</strong> (the one that feeds the financial GL). Run a separate close for each book you
                maintain (for example, close GAAP for the financial GL; tax books are reviewed at year-end).</li>
              <li>Choose <strong>Month</strong> (a fiscal year + month) or <strong>Year</strong> (a full fiscal year), then
                <strong>Start / Resume</strong>. A close in progress is saved, so you can leave and come back to it. The
                <strong>Recent closes</strong> list shows every period with its status and a 🔒 lock badge.</li>
            </ul>

            <h3>The month-end checklist</h3>
            <p>Each step shows the live data for the period and lets you act, then mark it done:</p>
            <ol>
              <li><strong>Record additions</strong> — review capital purchases placed in service in the period. Any asset
                below your <strong>capitalization threshold</strong> is flagged so you can confirm it belongs on the register.</li>
              <li><strong>Record disposals</strong> — review assets sold, scrapped, or retired in the period (cost,
                accumulated depreciation, gain/loss). You can <strong>post the disposal journal entries</strong> here.</li>
              <li><strong>Capitalize WIP</strong> — review Construction-in-progress assets and <strong>capitalize</strong>
                completed ones, which moves them into service and begins depreciation.</li>
              <li><strong>Process &amp; post depreciation</strong> — compute the period's depreciation and <strong>post it to
                the GL</strong>, allocated by department / cost center. Fully-depreciated assets that would still compute
                depreciation are flagged for review.</li>
              <li><strong>Check for impairments</strong> — review flagged assets and record any impairment loss (from the
                asset's Adjustments tab).</li>
              <li><strong>Reconcile subledger to GL</strong> — compare the register to the GL control accounts and clear or
                acknowledge any variance (see below). <em>Required to finalize.</em></li>
              <li><strong>Generate reports</strong> — run and file the Fixed Asset Register, Depreciation Summary, and
                Additions / Disposals reports for your records.</li>
              <li><strong>Finalize &amp; lock</strong> — freeze the period.</li>
            </ol>

            <h3>What gets posted to the GL</h3>
            <p>
              The close writes <strong>real, balanced journal entries</strong> into the stored GL layer (visible under
              <a href="#" @click.prevent="select('books')">Books → GL and Journals</a>). The accounts come from your
              <strong>GL posting defaults</strong> (per-asset overrides win where set):
            </p>
            <table class="manual-table">
              <thead><tr><th>Event</th><th>Debit</th><th>Credit</th></tr></thead>
              <tbody>
                <tr><td>Period depreciation (by department)</td><td>Depreciation Expense</td><td>Accumulated Depreciation</td></tr>
                <tr><td>Capitalize WIP</td><td>Fixed Asset cost</td><td>Construction-in-progress (CWIP)</td></tr>
                <tr><td>Disposal</td><td>Accum. depreciation + Proceeds (+ Loss)</td><td>Asset cost (+ Gain)</td></tr>
                <tr><td>Year-end roll-forward</td><td>Retained Earnings</td><td>Depreciation Expense</td></tr>
              </tbody>
            </table>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Every close posting is <strong>tagged to its period</strong>, which makes posting <strong>idempotent</strong>:
              re-running a step (for example, re-posting depreciation after a correction) replaces the prior entries rather
              than duplicating them. Manage the accounts these entries use in
              <a href="#" @click.prevent="select('books')">Books → GL and Journals → Chart of accounts</a> (the
              <strong>posting defaults</strong>: asset cost, accumulated depreciation, depreciation expense, CWIP, gain/loss,
              proceeds clearing, and retained earnings).
            </v-alert>

            <h3>Reconciling the subledger to the GL</h3>
            <p>
              The <strong>Reconcile</strong> step compares the Fixed Asset Register (the subledger) to the GL
              control-account balances — <strong>cost</strong>, <strong>accumulated depreciation</strong>, and
              <strong>net book value</strong> — and shows the variance per account. A green <em>Balanced</em> badge means
              they agree; otherwise the variance is shown so you can clear it (post an adjusting entry) or
              <strong>acknowledge</strong> it and finalize anyway.
            </p>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              When you <em>first</em> adopt closes, the GL won't yet hold the asset's full history, so the register
              (life-to-date) and the GL (only what's been posted) will differ — that opening variance is expected. Post an
              opening-balance entry to clear it, or acknowledge it. Once you run closes forward period over period, the two
              stay in step.
            </v-alert>

            <h3>Finalizing &amp; the period lock</h3>
            <p>
              <strong>Finalize &amp; lock</strong> becomes available once the required steps are done and the reconciliation
              has been run. Finalizing snapshots the period's totals and sets the period to <strong>Closed</strong>. A
              closed period is <strong>locked</strong>:
            </p>
            <ul>
              <li>Any change whose effective date falls inside the closed period is <strong>rejected</strong> — including
                <strong>GL journal entries</strong> (for that book), and <strong>disposals, impairments, and asset
                financial-date / cost edits</strong> (gated by the <strong>primary</strong> book's locked periods, since
                that book is the subledger that feeds the GL).</li>
              <li>Edits to non-financial fields (location, custodian, notes, and so on) are <strong>not</strong> blocked.</li>
            </ul>

            <h3>Year-end close</h3>
            <p>The year-end checklist includes everything above, plus:</p>
            <ul>
              <li><strong>Final month-end close</strong> — confirm the final month is closed and its depreciation posted.</li>
              <li><strong>Physical inventory</strong> — confirm you've verified high-value / mobile assets still exist.</li>
              <li><strong>Update tax books</strong> — recompute tax depreciation (MACRS / §179) and review book-vs-tax
                differences.</li>
              <li><strong>Roll-forward</strong> — finalizing a year close automatically posts the <strong>roll-forward</strong>
                that clears the year's depreciation expense into <strong>Retained Earnings</strong> and locks the year.</li>
            </ul>

            <h3>Reopening a closed period</h3>
            <p>
              If you must correct a closed period, use <strong>Reopen</strong> (requires the close permission). Reopening
              <strong>reverses all of that close's posted entries</strong>, returns the period to <em>in&nbsp;progress</em>,
              and unlocks it so corrections can be made — then you re-run and finalize again. The reopen, the reversed
              entries, and the re-close are all audited.
            </p>
            <v-alert type="warning" variant="tonal" density="comfortable" class="manual-callout">
              Running the close needs the <strong>“Run month-end / year-end close &amp; reopen periods”</strong> capability
              (included in the Finance role). Because closing posts to the GL and locks the books, keep this permission to
              the people responsible for the close.
            </v-alert>
          </section>

          <!-- TAX RULES -->
          <section v-show="isShown('taxrules')" class="manual-section">
            <h2>Tax rule sets</h2>
            <p>
              A <strong>tax rule set</strong> defines the depreciation methods and statutory limits for a jurisdiction
              (for example US federal, or a particular state). A book consults its assigned rule set to compute depreciation.
            </p>

            <h3>The Tax rules editor</h3>
            <p>The screen has two parts: <strong>identity fields</strong> on the left (Name, Jurisdiction, Version, Effective date, Source note, Active) and a <strong>JSON editor</strong> holding the rule body. The toolbar offers:</p>
            <ul>
              <li><strong>New</strong> / <strong>Upload JSON</strong> — start a fresh set or load one from a file.</li>
              <li><strong>Format</strong> — validate and tidy (pretty-print) the JSON. <em>Save is disabled while the JSON is invalid.</em></li>
              <li><strong>Regenerate method catalog</strong> — auto-fill the full set of standard depreciation methods, so you rarely have to type the <code>methods</code> list by hand.</li>
              <li><strong>Export</strong> — download the set as a JSON file.</li>
              <li><strong>Activate</strong> — make this version the one in effect for its jurisdiction (this deactivates other versions for the same jurisdiction).</li>
              <li><strong>Save</strong> / <strong>Delete</strong>.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              The fastest way to build a set: click <strong>New</strong>, fill the identity fields, click <strong>Regenerate method catalog</strong> to populate the standard methods, adjust the <code>limits</code> for your jurisdiction, then <strong>Format</strong>, <strong>Save</strong>, and <strong>Activate</strong>. Finally, assign it to a book on <strong>Financial → Books</strong>.
            </v-alert>

            <h3>A quick JSON primer</h3>
            <p>The rule body is written in JSON. A few rules cover almost everything you need:</p>
            <ul>
              <li>The whole document is an <strong>object</strong> wrapped in curly braces.</li>
              <li>Inside, you list <strong>"key": value</strong> pairs, separated by commas.</li>
              <li>Keys and text values are wrapped in <strong>double quotes</strong> — <code>"like this"</code>.</li>
              <li>Numbers (<code>60</code>, <code>0.15</code>) and <code>true</code> / <code>false</code> / <code>null</code> are written <strong>without</strong> quotes.</li>
              <li>A <strong>list</strong> uses square brackets, with items separated by commas. Objects and lists can nest inside each other.</li>
              <li>Do <strong>not</strong> put a comma after the last item in an object or list — a trailing comma is the most common mistake. Use <strong>Format</strong> to catch errors.</li>
            </ul>

            <h3>Top-level fields</h3>
            <table class="manual-table">
              <thead><tr><th>Field</th><th>Type</th><th>Purpose</th></tr></thead>
              <tbody>
                <tr><td>schema</td><td>text</td><td>Optional tag identifying the file format.</td></tr>
                <tr><td>jurisdiction</td><td>text</td><td>The jurisdiction this set governs (e.g. <code>US-FED</code>, <code>US-CA</code>). Also set by the identity field.</td></tr>
                <tr><td>name</td><td>text</td><td>Display name for the rule set.</td></tr>
                <tr><td>version</td><td>text</td><td>Version label; must be unique within a jurisdiction.</td></tr>
                <tr><td>effectiveDate</td><td>date text</td><td>When the rules take effect, as <code>"YYYY-MM-DD"</code>.</td></tr>
                <tr><td>sourceNote</td><td>text</td><td>Free-form note about the source or authority.</td></tr>
                <tr><td>books</td><td>list of text</td><td>Reference list of the books this set is intended for.</td></tr>
                <tr><td>conventions</td><td>list of text</td><td>Conventions in use (reference): <code>half_year</code>, <code>mid_quarter</code>, <code>mid_month</code>, <code>full_month</code>, <code>none</code>.</td></tr>
                <tr><td>limits</td><td>object</td><td>Statutory reference limits — §179, bonus, de-minimis (see below).</td></tr>
                <tr><td>assetLives</td><td>list of objects</td><td>Reference list of class lives, each <code>{ code, label, months }</code>.</td></tr>
                <tr><td>methods</td><td>list of objects</td><td><strong>The calculation catalog the engine actually uses</strong> (see below).</td></tr>
              </tbody>
            </table>
            <p class="quiet">Name, jurisdiction, version, effective date, source note, and active status are also editable in the identity fields beside the editor; keeping them in the JSON too is fine.</p>

            <h4>The <code>limits</code> object</h4>
            <ul>
              <li><strong>section179</strong>: <code>deductionLimit</code> (number), <code>phaseOutBegins</code> (number), <code>cannotCreateLoss</code> (true/false).</li>
              <li><strong>bonusDepreciation</strong>: <code>qualifiedPropertyPercent</code> (e.g. <code>100</code>), <code>effectivePlacedInServiceAfter</code> (date text).</li>
              <li><strong>deMinimisSafeHarbor</strong>: <code>defaultThreshold</code> (number), <code>auditedFinancialStatementThreshold</code> (number).</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              These limits <em>document</em> the jurisdiction’s caps for reference. The actual §179 and bonus amounts applied to a given
              asset are the values you enter on that asset’s <strong>Books</strong> tab.
            </v-alert>

            <h3>Inside <code>methods</code> — the calculation catalog</h3>
            <p>
              Each entry in <code>methods</code> is one depreciation method. When you pick a method on an asset’s Books tab, the engine
              matches your choice by its <code>code</code> and computes depreciation using that entry’s settings.
            </p>
            <table class="manual-table">
              <thead><tr><th>Field</th><th>Type</th><th>Purpose</th></tr></thead>
              <tbody>
                <tr><td>code</td><td>text</td><td>Unique identifier; this is what a book’s “method” selection points to.</td></tr>
                <tr><td>family</td><td>text</td><td>Grouping shown in the picker — e.g. <code>MACRS</code>, <code>ACRS</code>, <code>GAAP</code>, <code>Manual</code>, <code>Lease</code>.</td></tr>
                <tr><td>label</td><td>text</td><td>Human-readable name shown in pickers and reports.</td></tr>
                <tr><td>formula</td><td>text</td><td>How depreciation is calculated (see values below).</td></tr>
                <tr><td>lifeMonths</td><td>number</td><td>Recovery period in months (e.g. <code>60</code> = 5 years).</td></tr>
                <tr><td>defaultConvention</td><td>text</td><td>First/last-year convention this method applies (overrides the book’s convention).</td></tr>
                <tr><td>rateMultiplier</td><td>number</td><td>Declining-balance rate: <code>2</code> = 200%, <code>1.5</code> = 150%.</td></tr>
                <tr><td>switchToStraightLine</td><td>true/false</td><td>For declining balance, switch to straight-line once it yields a larger deduction (typical for MACRS).</td></tr>
                <tr><td>rates</td><td>list of numbers</td><td>For the <code>rate_table</code> formula: the per-year fractions of basis (should total ≈ 1.0).</td></tr>
                <tr><td>fallbackFormula</td><td>text</td><td>Used when a rate table is empty (e.g. <code>straight_line</code>).</td></tr>
                <tr><td>system</td><td>text</td><td>Optional label such as <code>GDS</code>, <code>ADS</code>, or <code>ACRS</code>.</td></tr>
              </tbody>
            </table>

            <h4>Accepted <code>formula</code> values</h4>
            <table class="manual-table">
              <thead><tr><th>Value</th><th>Behavior</th></tr></thead>
              <tbody>
                <tr><td><code>straight_line</code></td><td>Even amount over the life. Used as the fallback for any unrecognized formula.</td></tr>
                <tr><td><code>declining_balance</code></td><td>Accelerated, using <code>rateMultiplier</code>.</td></tr>
                <tr><td><code>macrs_declining_balance</code></td><td>Declining balance that switches to straight-line (the standard MACRS behavior).</td></tr>
                <tr><td><code>sum_of_years_digits</code></td><td>Accelerated sum-of-years-digits.</td></tr>
                <tr><td><code>rate_table</code></td><td>Applies the per-year fractions in <code>rates</code>.</td></tr>
                <tr><td><code>acrs_alternate_straight_line</code></td><td>ACRS alternate (modified) straight-line.</td></tr>
                <tr><td><code>manual</code></td><td>You enter each year’s amount on the asset (no automatic calculation).</td></tr>
              </tbody>
            </table>

            <h3>Sample rule set</h3>
            <p>A compact example showing the three most common method styles — straight-line, declining balance, and a rate table:</p>
            <pre class="manual-code">{{ sampleRuleSet }}</pre>

            <v-alert type="warning" variant="tonal" density="comfortable" class="manual-callout">
              Rule sets ship as starter templates. Always confirm current tax law, rates, and elections before relying on a set for a filing.
            </v-alert>
            <p>To put a set to work, open <strong>Financial → Books</strong> and assign it to a book.</p>
          </section>

          <!-- TEMPLATES -->
          <section v-show="isShown('templates')" class="manual-section">
            <h2>Templates</h2>
            <p>
              Templates speed up asset entry and standardize data. A template defines default values (category, useful life,
              depreciation method, GL accounts, business-use %, etc.) and a set of <strong>custom fields</strong> (text, number, date, or
              checkbox) that should be captured for that kind of asset.
            </p>
            <h3>Creating a template</h3>
            <ol>
              <li>Open <strong>Templates</strong> and give the template a name and description.</li>
              <li>Set the default values new assets should start with.</li>
              <li>Add custom fields, marking any that are required.</li>
              <li>Save. The template is now selectable from the <strong>Template</strong> picker when creating an asset.</li>
            </ol>
            <p>Choosing a template on a new asset fills the defaults and adds its custom fields to the Details tab.</p>

            <h3>Editing &amp; deleting templates</h3>
            <p>
              The templates list (right) is searchable and paginated, and shows how many fields each template has and how many
              assets currently use it. Use the <strong>pencil</strong> to load a template back into the editor and save your changes,
              or the <strong>trash</strong> to delete it.
            </p>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Deleting a template is safe for your data: assets that used it <strong>keep all their values</strong> and are simply
              unlinked from the template. The only other effect is that the template is no longer offered when creating new assets.
              The confirmation dialog tells you how many assets are affected before you proceed.
            </v-alert>
          </section>

          <!-- PM -->
          <section v-show="isShown('pm')" class="manual-section">
            <h2>Preventative maintenance</h2>
            <p>
              The <strong>Maintenance</strong> screen manages reusable <strong>PM plans</strong> — standard procedures performed on a
              schedule — which you then attach to specific assets and complete over time.
            </p>

            <h3>Creating a PM plan</h3>
            <ol>
              <li>On <strong>Maintenance</strong>, click <strong>New plan</strong>.</li>
              <li>Name the plan and set its <strong>frequency</strong> (every N days, weeks, months, quarters, bi-yearly, or years).</li>
              <li>Add ordered <strong>steps</strong> (the checklist a technician follows), each with an optional time estimate — the plan’s total estimated time totals automatically.</li>
              <li>Add <strong>components / parts</strong> (part number, description, supplier, cost) to capture expected materials and cost.</li>
              <li>Add <strong>guidance photos</strong> (diagrams, part locations, before/after) with captions — these are shown to the technician while completing the service.</li>
              <li>Save the plan.</li>
            </ol>

            <h3>Attaching a plan to an asset</h3>
            <p>
              Open the asset, go to the <strong>PM</strong> tab, choose a plan, and set the interval, first-due date, and an end date
              (it pre-fills to the asset’s depreciation end). The schedule now tracks the next due date and raises alerts as it approaches or passes.
            </p>

            <h3>Completing (closing) a service</h3>
            <ol>
              <li>On the asset’s <strong>PM</strong> tab, click <strong>Complete</strong> on an active schedule.</li>
              <li>The form records who is closing it (you), shows any <strong>guidance photos</strong>, and lets you tick off each step.</li>
              <li>Give 1–5★ <strong>condition ratings</strong>: Safety (is it safe?), Physical condition, and Operating condition.</li>
              <li>Add <strong>completion notes</strong> and <strong>photos</strong> of the work, confirm the parts cost, and capture a <strong>signature</strong> (required).</li>
              <li>Click <strong>Mark complete</strong>. The next-due date rolls forward automatically (the schedule closes if it has passed its end date), and the cost is recorded to the PM book.</li>
            </ol>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Completed forms — with signature, ratings, notes, and photos — are viewable from both the asset’s PM tab and the
              <strong>Completed PM forms</strong> list on the Maintenance screen.
            </v-alert>

            <h3>Dynamic scheduling — usage meters &amp; the lifespan wear curve</h3>
            <p>
              Beyond a fixed calendar interval, a schedule’s next-due date can adjust to real-world use. When usage and
              age signals are enabled, the next service is due at the <strong>earliest</strong> of three triggers — the
              calendar interval, a projected usage threshold, or an age-compressed date — and the asset’s PM list shows a
              small badge (📅 date, ⏱ usage, or 📉 age) indicating which one is driving the date.
            </p>
            <ul>
              <li>
                <strong>Usage meters.</strong> Add one or more meters to a PM plan (e.g. <em>Operating Hours</em>, kWh,
                gallons, cycles) with a “due every” threshold. Record the current reading when completing a service, or
                anytime via <strong>Log reading</strong> on the asset’s PM tab. DepreCore infers the usage <em>rate</em>
                from successive readings and pulls the due-date in when a machine is running hard; crossing a threshold
                raises a usage alert (e.g. “Operating Hours 512/500”).
              </li>
              <li>
                <strong>Lifespan wear curve.</strong> Turn on “Tighten the interval as the asset ages” on a plan to shorten
                the service interval as an asset approaches its estimated life (from the asset’s useful-life months). New
                equipment is serviced on the base cadence; near end-of-life it is serviced more often, along a curve you
                tune in PM settings.
              </li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Both signals are <strong>opt-in</strong>: an administrator enables “Usage-based scheduling” and the “Lifespan
              wear curve” (with its end-of-life factor and aggressiveness) under <strong>Admin → Application Configuration →
              Preventative maintenance defaults</strong>. A nightly job re-projects due-dates so usage/age schedules stay
              current even when an asset isn’t serviced for a while; admins can also run it on demand with <strong>Run
              now</strong>.
            </v-alert>
          </section>

          <!-- PARTS -->
          <section v-show="isShown('parts')" class="manual-section">
            <h2>Parts inventory</h2>
            <p>
              <strong>Parts inventory</strong> (under Maintenance) is a standalone stockroom for maintenance parts and supplies. It is
              deliberately separate from the asset register — parts are consumables, not depreciating assets.
            </p>
            <h3>Adding a part</h3>
            <ol>
              <li>Open <strong>Maintenance → Parts inventory</strong> and click <strong>New part</strong>.</li>
              <li>Enter the part number, name, category, unit of measure, unit cost, and a reorder point (used for low-stock flagging).</li>
              <li>Add identification details — measurements, manufacturer part number, barcode, and photos.</li>
              <li>Pick a <strong>supplier</strong> from your Contacts (vendors, service providers, or contractors).</li>
              <li>Save, then add stock locations and movements.</li>
            </ol>
            <h3>Stock, locations &amp; reservations</h3>
            <ul>
              <li>Store a part in one or more <strong>locations</strong> (chosen from your Work Location contacts), each with an <strong>aisle</strong> and <strong>bin</strong>.</li>
              <li>Each location tracks quantity on hand and how much is <strong>reserved</strong>; available = on hand − reserved.</li>
              <li>Record <strong>movements</strong>: receive (add stock), issue (consume), adjust (set an absolute count), reserve, and unreserve. Every movement is logged with history.</li>
              <li>Parts at or below their reorder point are flagged <strong>low stock</strong>; use the low-stock filter to see what to reorder.</li>
            </ul>
          </section>

          <!-- CONTACTS -->
          <section v-show="isShown('contacts')" class="manual-section">
            <h2>Contacts &amp; CRM</h2>
            <p>
              <strong>Contacts</strong> is a directory of the people and organizations you work with: <em>employees, vendors, service
              providers, contractors, work locations,</em> and <em>other</em>. The form adapts to the type you choose.
            </p>
            <h3>Managing contacts</h3>
            <ul>
              <li>Use the type selector and filter box to find records; create a contact with <strong>New contact</strong>.</li>
              <li>Capture name/organization, international-friendly address and phone, and email.</li>
              <li><strong>Type-specific fields</strong>: employee ID/department/manager/start date; contractor tax ID or business license; vendor and service-provider star rating and credit term.</li>
              <li><strong>Location map</strong> — once an address is entered, the contact card can show an embedded <strong>Google map</strong> of the location, with an <em>Open in Google Maps</em> link. For a new contact the map appears on a <em>Show map</em> click; when you open an existing contact with an address it’s shown automatically.</li>
              <li>Keep a per-contact <strong>notes log</strong> for running history.</li>
            </ul>
            <h3>How contacts connect to the rest of the app</h3>
            <ul>
              <li><strong>Work location</strong> contacts populate the <strong>Location</strong> dropdown on the asset form and are the locations where parts stock is held.</li>
              <li><strong>Vendor / service-provider / contractor</strong> contacts populate the asset form’s <strong>Vendor</strong> dropdown and are selectable as the <strong>supplier</strong> on parts.</li>
              <li>Employee records can be brought in automatically from Workday when that connector is configured (see <a href="#" @click.prevent="select('admin')">Administration</a>).</li>
            </ul>
          </section>

          <!-- ASSIGNMENTS -->
          <section v-show="isShown('assignments')" class="manual-section">
            <h2>Assignments (custody)</h2>
            <p>
              <strong>Assignments</strong> tracks who has custody of which asset. Assign an asset to an employee, department, or location,
              and the full custody history is retained so you always know where an asset is and who is responsible for it.
            </p>
            <ul>
              <li>The employee list is filterable and paginated.</li>
              <li>Assign an asset, then <strong>release</strong> it (with a reason) when custody changes — both events are kept in the traceability history.</li>
              <li>Employees can be added here directly, or synced from Workday.</li>
            </ul>
          </section>

          <!-- ALERTS -->
          <section v-show="isShown('alerts')" class="manual-section">
            <h2>Alerts &amp; reminders</h2>
            <p>
              The <strong>Alerts</strong> screen surfaces everything that needs attention: overdue and upcoming tasks, preventative
              maintenance due/overdue, and warranties or leases about to expire. Each alert has a <strong>severity</strong> — <em>critical</em>
              (overdue/expired, or within seven days) or <em>warning</em>.
            </p>
            <h3>Working alerts</h3>
            <ul>
              <li><strong>Run scan</strong> recalculates the current alerts from your data.</li>
              <li><strong>Acknowledge</strong> an alert to mark it in-progress; <strong>Dismiss</strong> one to stop it reappearing.</li>
              <li>Filter by status and type, and use the summary tiles for a quick count of open and critical items.</li>
            </ul>

            <h3>Delivery channels</h3>
            <p>Beyond the on-screen list, alerts can be pushed outward (all configured in <a href="#" @click.prevent="select('admin')">Administration</a>):</p>
            <ul>
              <li><strong>Email digest</strong> — when email is enabled and a mail server is configured, new alerts are emailed to the recipient list. You can also trigger <strong>Email digest now</strong> from the Alerts screen.</li>
              <li><strong>Webhook</strong> — each new alert can be posted to an external URL as a JSON object, optionally signed for authenticity. Useful for chat tools or custom automation.</li>
              <li><strong>Microsoft Teams</strong> — post a digest card of new alerts to a Teams channel or chat (see <a href="#" @click.prevent="select('teams')">Microsoft Teams integration</a>).</li>
              <li><strong>ServiceNow incident</strong> — raise a ticket from any alert (see below).</li>
            </ul>

            <h3>Forwarding an alert to ServiceNow</h3>
            <p>
              When the ServiceNow connection is configured, each open alert shows a <strong>ServiceNow</strong> action. Click it to create
              an incident; the alert’s <strong>Ticket</strong> column then shows the incident number as a link straight into ServiceNow.
              Re-clicking returns the existing ticket rather than creating a duplicate. With <em>auto-create</em> enabled, the system raises
              an incident automatically for each new <em>critical</em> alert. Alert severity maps to the incident’s impact/urgency.
              See <a href="#" @click.prevent="select('servicenow')">ServiceNow integration</a> for setup.
            </p>
          </section>

          <!-- SERVICENOW -->
          <section v-show="isShown('servicenow')" class="manual-section">
            <h2>ServiceNow integration</h2>
            <p>
              DepreCore connects to ServiceNow in two directions, both configured in <strong>Administration → ServiceNow integration</strong>:
              pushing <strong>incidents</strong> out, and pulling <strong>asset data</strong> in from the CMDB.
            </p>

            <h3>Connecting</h3>
            <ol>
              <li>Enter your ServiceNow <strong>instance URL</strong> (e.g. <em>https://yourcompany.service-now.com</em>) and the username/password of an integration user.</li>
              <li>Click <strong>Test connection</strong> to confirm the credentials work.</li>
              <li>Save. The stored password is never displayed back; leave it blank to keep the existing value, or use <strong>Clear password</strong> to remove it.</li>
            </ol>

            <h3>Pushing incidents (tickets)</h3>
            <ul>
              <li>Turn on <strong>Allow submitting alerts as incidents</strong> to enable ticket creation.</li>
              <li>Optionally turn on <strong>Auto-create incidents for new critical alerts</strong> so critical items raise tickets automatically.</li>
              <li>Set the incident table (usually <em>incident</em>) and, if you wish, a default assignment group and caller.</li>
              <li>Tickets are then raised from the <strong>Alerts</strong> screen, with the incident number linked back to ServiceNow.</li>
            </ul>

            <h3>Pulling assets from the CMDB</h3>
            <p>This populates your asset register from ServiceNow configuration items (CIs):</p>
            <ol>
              <li>Set the <strong>CMDB CI table</strong> (for example <em>cmdb_ci_hardware</em>) and, optionally, a filter to limit which CIs are pulled and a maximum number per sync.</li>
              <li>Review the <strong>field mapping</strong> — which CI fields populate which asset fields. Sensible hardware defaults are provided; adjust as needed.</li>
              <li>Click <strong>Sync CMDB now</strong>. The last sync time and a result summary are shown.</li>
            </ol>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Re-syncing is safe: existing assets are matched (by their ServiceNow identifier, then serial number, then asset tag) and
              <em>updated in place</em> rather than duplicated. CMDB-sourced assets receive default depreciation books like any other asset,
              which you can then refine on the Books tab.
            </v-alert>
          </section>

          <!-- MICROSOFT TEAMS -->
          <section v-show="isShown('teams')" class="manual-section">
            <h2>Microsoft Teams integration</h2>
            <p>
              DepreCore can post newly raised alerts to a <strong>Microsoft Teams</strong> channel or chat. One digest card is sent per
              alert cycle, alongside (or instead of) email, webhook, and ServiceNow delivery. Configure it in
              <strong>Administration → Integrations → Microsoft Teams</strong>.
            </p>
            <h3>Connecting</h3>
            <ol>
              <li>In Teams, create an incoming webhook for the target channel — a <strong>Workflows</strong> “post to a channel when a
                webhook request is received” flow (recommended), or a legacy <strong>Incoming Webhook</strong> connector.</li>
              <li>Paste the webhook URL into DepreCore and pick the matching <strong>card format</strong>: <em>Adaptive Card (Workflows)</em>
                for the modern flow, or <em>MessageCard (legacy connector)</em>.</li>
              <li>Choose a <strong>minimum severity</strong> to post (e.g. Warning and above) so the channel only gets what matters, turn on
                <strong>Enable Teams delivery</strong>, and click <strong>Send test card</strong> to confirm it lands in the channel.</li>
            </ol>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Cards are colour-coded by severity and summarize the pending alerts (title, detail, due date, asset). Each alert is delivered
              once across all channels. <em>Note:</em> this “Teams” (Microsoft Teams chat) is unrelated to <strong>Admin → Users &amp;
              Teams</strong>, which groups your DepreCore users.
            </v-alert>
          </section>

          <!-- ADMIN -->
          <section v-show="isShown('admin')" class="manual-section">
            <h2>Administration</h2>
            <p>
              <strong>Admin</strong> (admin role) is where the application is configured. It is split into sub-screens in the
              navigation rail: <strong>Users &amp; Teams</strong>, <strong>Password &amp; Security</strong>,
              <strong>Activity &amp; Audit Trail</strong>, <strong>Application Configuration</strong> (companies, application
              settings, asset classes, depreciation zones, Section 179 limits, §280F passenger-auto limits, asset ID templates, asset categories,
              asset departments, PM categories, parts categories, maintenance defaults, tax rule sets), and
              <strong>Integrations</strong> (email, webhook, Microsoft Teams, ServiceNow, Workday). Each is described below.
            </p>

            <h3>Users &amp; roles</h3>
            <ul>
              <li>Create and edit users — name, email, team, role, status, and password.</li>
              <li>The list paginates and is filterable. A user’s role controls what they can see and do.</li>
              <li><strong>Company access</strong> — assign which companies a user may see and switch between (administrators
                always see every company). See <a href="#" @click.prevent="select('companies')">Companies</a>.</li>
              <li>You can require a <strong>password change at next sign-in</strong>, and a locked account (after too many
                failed sign-ins) shows an <strong>Unlock</strong> action — see
                <a href="#" @click.prevent="select('security')">Password &amp; security</a>.</li>
            </ul>

            <h3>Companies</h3>
            <p>Add, edit, and dispose/restore companies, each with its own books, GL, and data. Covered under
              <a href="#" @click.prevent="select('companies')">Companies</a>.</p>

            <h3>Password &amp; security</h3>
            <p>Password complexity/expiry/history rules and account lockout. Covered under
              <a href="#" @click.prevent="select('security')">Password &amp; security</a>.</p>

            <h3>Activity &amp; audit trail</h3>
            <p>A searchable, exportable log of every change made in the system. Covered under
              <a href="#" @click.prevent="select('security')">Password &amp; security</a>.</p>

            <h3>Teams</h3>
            <p>Group users into teams. Select a team to edit or delete it (a team in use by members can’t be deleted until they’re reassigned).</p>

            <h3>Roles</h3>
            <p>Create and edit roles and the capabilities they grant — including custom roles. See <a href="#" @click.prevent="select('roles')">Roles &amp; permissions</a>.</p>

            <h3>Application settings</h3>
            <p>Server name, allowed cross-origin domains, and the database driver/path (read-only) used by this deployment.</p>

            <h3>Asset ID templates</h3>
            <p>
              Define naming patterns that auto-assign asset tags. Put <strong>#</strong> characters where the running number goes —
              it’s zero-padded to that width and increments automatically. For example <code>DT-######</code> produces DT-000001,
              DT-000002, … and <code>T-A#####</code> produces T-A00001. Each template has a “next number” you can set (e.g. to
              continue an existing sequence), and a live preview of the next tag.
            </p>
            <p>
              Assign a template to a category in <strong>Asset categories</strong> (below). Then, when someone creates an asset and
              picks that category, the <strong>Asset ID is filled in automatically</strong> from the template — they can still type
              their own ID to override it. Categories with no template use the default <code>MA-#####</code> sequence. Deleting a
              template never renames existing assets; it just unassigns the affected categories.
            </p>

            <h3>Asset classes</h3>
            <p>
              A managed catalog of IRS asset classes (class number, GDS/ADS recovery periods), pre-loaded from the IRS tables —
              commonly-used assets, manufacturing industry, and business activity. <strong>Create, edit, and delete</strong> entries here;
              filter by source or search by description/class number. These power the “Look up IRS asset class” search when you set a
              category’s class number. Deleting a class never changes assets or categories — it only removes it from the lookup.
            </p>

            <h3>Asset categories</h3>
            <p>
              Create, rename, and delete the categories offered in the asset form’s <strong>Category</strong> dropdown — so users
              choose from a controlled list instead of typing free text. The list is searchable and paginated and shows how many
              assets use each category, plus the <strong>ID template</strong> assigned to it (chosen when you create or edit a category).
            </p>
            <ul>
              <li><strong>Renaming</strong> a category automatically updates every asset that uses it, so it’s also the way to merge two categories (rename one to match the other).</li>
              <li><strong>Deleting</strong> a category leaves existing assets’ values untouched; the category simply stops appearing in the dropdown. The confirmation tells you how many assets are affected first.</li>
              <li><strong>Asset class number</strong> — an optional number on the category that is <strong>shared by every asset in it</strong>. New assets inherit it automatically, and changing it cascades to all existing assets in the category. It appears (read-only) on each asset’s Details tab. Use the built-in <strong>“Look up IRS asset class”</strong> search to pick from the IRS tables — <em>commonly-used assets</em>, <em>manufacturing industry</em>, and <em>business activity</em>; each result is tagged Common, Manufacturing, or Business and shows its GDS/ADS recovery periods. You can also type a custom number.</li>
            </ul>

            <h3>Asset departments</h3>
            <p>
              Works exactly like Asset categories, but for the asset form’s <strong>Department</strong> dropdown — create, rename
              (cascades to assets, and merges by renaming to match), and delete (assets keep their value; it just leaves the dropdown).
            </p>

            <h3>PM categories</h3>
            <p>
              The same management, but for the <strong>Category</strong> dropdown on preventative-maintenance plans — and kept
              <strong>separate from asset categories</strong>. Renaming cascades to PM plans; deleting leaves existing plans’ values
              and removes the option from the dropdown.
            </p>

            <h3>Parts categories</h3>
            <p>
              The same management again, for the <strong>Category</strong> dropdown on parts inventory — separate from asset and PM
              categories, and pre-loaded with a starter set (Electrical, Plumbing, Structural Component, Electronic Component, Fire
              Safety, Mechanical Safety, Other). Renaming cascades to parts; deleting leaves existing parts’ values.
            </p>

            <h3>Email &amp; alerts (SMTP)</h3>
            <ul>
              <li>Turn email alerts on/off, set how many days ahead to warn, and the recipient list.</li>
              <li>Configure the mail server (host, port, security, username, from-address). The password is write-only — blank keeps the stored value.</li>
              <li>Use <strong>Send test</strong> to verify delivery.</li>
            </ul>

            <h3>Alert webhook</h3>
            <p>
              Enable webhook delivery and set the destination URL to have each new alert posted as a JSON object. An optional signing
              secret adds a verification signature to each request. <strong>Send test event</strong> confirms the endpoint works, and a sample
              payload is shown for whoever builds the receiving side.
            </p>

            <h3>Microsoft Teams</h3>
            <p>Post alert digests to a Teams channel — webhook URL, card format, and minimum severity. Covered under <a href="#" @click.prevent="select('teams')">Microsoft Teams integration</a>.</p>

            <h3>ServiceNow integration</h3>
            <p>Connection, incident push, and CMDB pull settings — covered in detail under <a href="#" @click.prevent="select('servicenow')">ServiceNow integration</a>.</p>

            <h3>Maintenance (PM) defaults</h3>
            <p>
              Set the default maintenance frequency for newly attached plans and how many days ahead PM-due alerts should appear.
              This is also where you enable <strong>dynamic scheduling</strong>: <strong>usage-based scheduling</strong> (meters) and the
              <strong>lifespan wear curve</strong> (with its end-of-life interval factor and curve aggressiveness), plus the
              <strong>nightly recompute</strong> job (on/off, hour of day, and a <em>Run now</em> button). See
              <a href="#" @click.prevent="select('pm')">Preventative maintenance</a> for how these signals drive due-dates.
            </p>

            <h3>Workday connector</h3>
            <ul>
              <li>Configure the connection to your Workday tenant to sync employees, departments, and locations.</li>
              <li>Run a manual <strong>Sync workers</strong>, or enable <strong>automatic scheduled sync</strong> and set the interval in hours.</li>
              <li>Synced employees populate both the assignments employee list and the Contacts directory (with manager and start-date enrichment).</li>
            </ul>

            <h3>Tax rule sets</h3>
            <p>A quick reference list of the rule sets in the system; manage them fully on the <a href="#" @click.prevent="select('taxrules')">Tax rules</a> screen.</p>
          </section>

          <!-- ROLES -->
          <section v-show="isShown('roles')" class="manual-section">
            <h2>Roles &amp; permissions</h2>
            <p>
              Every user has one role, and a role is a set of <strong>capabilities</strong> (granular permissions such as “Create &amp; edit
              assets” or “Manage integrations”). Capabilities decide which screens appear and which actions are allowed. Roles are managed
              in <strong>Admin → Users &amp; Teams → Roles</strong>, where you can edit the built-in roles or create your own.
            </p>
            <h3>Built-in roles</h3>
            <table class="manual-table">
              <thead><tr><th>Role</th><th>Typical use &amp; access</th></tr></thead>
              <tbody>
                <tr><td><strong>Administrator</strong></td><td>Full access (every capability), including users, roles, settings, and integrations. Always retains all capabilities.</td></tr>
                <tr><td><strong>Finance</strong></td><td>Assets, books, reports, tax rules, maintenance, parts, contacts, assignments, alerts — everything except system administration.</td></tr>
                <tr><td><strong>Operations</strong></td><td>Day-to-day asset, maintenance, parts, contacts, scanning, assignments, and alert work. No financial or system configuration.</td></tr>
                <tr><td><strong>PM Admin</strong></td><td>Owns preventative maintenance: create/edit PM plans &amp; defaults, complete services, manage parts, and work alerts.</td></tr>
                <tr><td><strong>PM User</strong></td><td>Completes preventative maintenance and views assets, parts, and alerts — but can’t change PM plans.</td></tr>
                <tr><td><strong>Viewer</strong></td><td>Read-only access to dashboards, assets, maintenance, and reports.</td></tr>
              </tbody>
            </table>

            <h3>Custom roles (role editor)</h3>
            <p>In <strong>Admin → Users &amp; Teams</strong>, the <strong>Roles</strong> panel lets you tailor access:</p>
            <ul>
              <li><strong>New role</strong> — name it, then tick the capabilities it should grant (grouped by area: Assets, Maintenance, Finance, etc.).</li>
              <li><strong>Edit</strong> any role to change its name, description, or capabilities. Changes take effect the next time affected users sign in. The Administrator role can’t be restricted.</li>
              <li><strong>Delete</strong> a custom role once no users are assigned to it. Built-in roles can’t be deleted.</li>
              <li>Assign a role to a user in the user’s edit dialog; the role list there always reflects your current roles.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              If you expect a screen or button that isn’t there, your role likely doesn’t include the capability for it — an administrator
              can grant it on the Roles panel or move you to a different role.
            </v-alert>
          </section>

          <!-- COMPANIES -->
          <section v-show="isShown('companies')" class="manual-section">
            <h2>Companies (multi-company)</h2>
            <p>
              DepreCore can manage <strong>multiple companies</strong>, each with its own assets, books and general ledger, PM plans,
              alerts, reports, reference data (categories/locations/departments), contacts, templates, saved reports, parts, and
              employee directory. You work in one <strong>active company</strong> at a time.
            </p>
            <h3>Switching companies</h3>
            <p>
              When you have access to more than one company, a <strong>company switcher</strong> appears in the top bar. Choosing a
              company instantly re-scopes every screen — dashboard, assets, books, maintenance, alerts, reports, and so on — to that
              company. Your selection is remembered between visits.
            </p>
            <h3>Managing companies</h3>
            <p>Administrators manage companies in <strong>Admin → Application Configuration → Companies</strong>:</p>
            <ul>
              <li><strong>Add / edit</strong> a company — name, legal name, base currency, fiscal year-end month, and separate
                <strong>Federal</strong>, <strong>State</strong>, and (optional) <strong>Local</strong> tax IDs. A new company is
                created with the standard book set and the standard reference data so its ledger works immediately.</li>
              <li><strong>Dispose (archive)</strong> a company to retire it — all of its assets, books, GL, and history are
                <em>preserved</em>, but it’s hidden from the switcher and can’t be selected for new work. The last active company can’t be
                disposed. Disposed companies can be <strong>restored</strong> at any time.</li>
            </ul>
            <h3>Who can see which company</h3>
            <p>
              Each user is granted access to one or more companies (set in the user’s edit dialog — see
              <a href="#" @click.prevent="select('admin')">Administration</a>); the switcher only lists the companies they may use, and a
              user can’t reach another company’s data. <strong>Administrators see every company.</strong>
            </p>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              A few things are deliberately <strong>shared across all companies</strong>: the tax-rule-set catalog (each company still
              selects which set each of its books uses), IRS reference data (depreciation zones and §179 limits), the integrations
              (email/Teams/webhook/ServiceNow/Workday), and the users/roles and audit/security layer.
            </v-alert>
          </section>

          <!-- SECURITY -->
          <section v-show="isShown('security')" class="manual-section">
            <h2>Password &amp; security · audit trail</h2>

            <h3>Password &amp; account security policy</h3>
            <p>
              Administrators set the rules for locally managed passwords in <strong>Admin → Password &amp; Security</strong>. They are
              enforced whenever a password is set or changed and at sign-in:
            </p>
            <ul>
              <li><strong>Complexity</strong> — minimum length and required character classes (uppercase, lowercase, number, symbol),
                and a rule that a password may not contain the user’s name or email.</li>
              <li><strong>Rotation &amp; reuse</strong> — expire passwords after N days, block reuse of the last N passwords, and an
                optional minimum password age.</li>
              <li><strong>Account lockout</strong> — lock an account for a set number of minutes after too many failed sign-ins. A locked
                user is refused until the window passes or an administrator clicks <strong>Unlock</strong> on the user.</li>
            </ul>
            <p>
              The live rule preview shows users exactly what’s required. Users change their own password from the account menu
              (<strong>Change password</strong>); when a change is required (expired, or set by an admin) they’re prompted at sign-in.
            </p>

            <h3>Activity &amp; Audit Trail</h3>
            <p>
              <strong>Admin → Activity &amp; Audit Trail</strong> is a complete, searchable record of user activity — sign-ins and
              lockouts, password and permission changes, GL and data edits, imports, and every create/update/delete across the app.
            </p>
            <ul>
              <li>Filter by <strong>user</strong>, <strong>action</strong>, <strong>entity type</strong>, <strong>date range</strong>, or
                free-text search, with pagination.</li>
              <li>Each entry can expand to show the full <strong>before → after</strong> detail of what changed.</li>
              <li><strong>Export CSV</strong> for external review or retention.</li>
            </ul>
            <v-alert type="info" variant="tonal" density="comfortable" class="manual-callout">
              Because every change is captured here with full before/after detail, the audit trail is the system-of-record for change
              tracking — for example, each GL journal-entry edit is logged here and also surfaced inline via the entry’s
              <strong>history</strong> icon (see <a href="#" @click.prevent="select('books')">Books, depreciation &amp; tax</a>).
            </v-alert>
          </section>

          <div class="manual-footer quiet">DepreCore User Guide · select a topic on the left, or use Print / Save PDF for the full manual.</div>
        </div>
      </div>
    </v-card>
  </v-dialog>
</template>

<script>
export default {
  props: {
    modelValue: { type: Boolean, default: false }
  },
  emits: ['update:modelValue'],
  data() {
    return {
      active: 'overview',
      search: '',
      printing: false,
      sampleRuleSet: [
        '{',
        '  "schema": "deprecore.taxRuleSet.v1",',
        '  "jurisdiction": "US-CA",',
        '  "name": "California depreciation",',
        '  "version": "2026.1",',
        '  "effectiveDate": "2026-01-01",',
        '  "sourceNote": "Confirm against current state law before filing.",',
        '  "books": ["GAAP", "STATE"],',
        '  "conventions": ["half_year", "mid_quarter", "mid_month", "none"],',
        '  "limits": {',
        '    "section179": {',
        '      "deductionLimit": 25000,',
        '      "phaseOutBegins": 200000,',
        '      "cannotCreateLoss": true',
        '    },',
        '    "bonusDepreciation": {',
        '      "qualifiedPropertyPercent": 0',
        '    }',
        '  },',
        '  "assetLives": [',
        '    { "code": "5Y", "label": "5-year property", "months": 60 },',
        '    { "code": "7Y", "label": "7-year property", "months": 84 }',
        '  ],',
        '  "methods": [',
        '    {',
        '      "code": "straight_line",',
        '      "family": "GAAP",',
        '      "label": "Straight-line",',
        '      "formula": "straight_line",',
        '      "lifeMonths": 60,',
        '      "defaultConvention": "half_year"',
        '    },',
        '    {',
        '      "code": "state_200db_5",',
        '      "family": "MACRS",',
        '      "label": "200% declining balance, 5-year",',
        '      "formula": "macrs_declining_balance",',
        '      "lifeMonths": 60,',
        '      "rateMultiplier": 2,',
        '      "switchToStraightLine": true,',
        '      "defaultConvention": "half_year"',
        '    },',
        '    {',
        '      "code": "acrs_5yr_table",',
        '      "family": "ACRS",',
        '      "label": "ACRS 5-year (statutory rates)",',
        '      "formula": "rate_table",',
        '      "lifeMonths": 60,',
        '      "rates": [0.15, 0.22, 0.21, 0.21, 0.21]',
        '    }',
        '  ]',
        '}'
      ].join('\n'),
      sections: [
        { id: 'overview', title: 'Getting started', icon: 'mdi-rocket-launch-outline', keywords: 'intro begin login sign in welcome' },
        { id: 'navigation', title: 'Interface & navigation', icon: 'mdi-view-dashboard-outline', keywords: 'menu rail theme dark light table sort filter top bar' },
        { id: 'dashboard', title: 'Dashboard', icon: 'mdi-chart-box-outline', keywords: 'home summary chart category value' },
        { id: 'assets', title: 'Assets — creating & managing', icon: 'mdi-archive-search-outline', keywords: 'asset register create edit import export mass edit workbench files notes tasks warranty' },
        { id: 'lifecycle', title: 'Asset lifecycle', icon: 'mdi-cash-remove', keywords: 'dispose disposal sale retire gain loss lease amortization impairment adjustment write down' },
        { id: 'barcodes', title: 'Barcodes & scanning', icon: 'mdi-barcode-scan', keywords: 'barcode label print scan camera tag' },
        { id: 'books', title: 'Books, depreciation & tax', icon: 'mdi-book-open-variant', keywords: 'book gaap federal depreciation general ledger gl method convention 179 bonus reports journal entry entries import export csv excel conflict merge history zone section 179 280f listed property passenger automobile luxury auto caps ads straight line mid-quarter limitation carryover taxable income macrs' },
        { id: 'close', title: 'Period close (month & year-end)', icon: 'mdi-calendar-lock', keywords: 'close month end year end period lock reconcile subledger gl roll forward retained earnings depreciation post reopen finalize wip capitalize disposal impairment audit' },
        { id: 'taxrules', title: 'Tax rule sets', icon: 'mdi-scale-balance', keywords: 'tax rules jurisdiction method limits activate version' },
        { id: 'templates', title: 'Templates', icon: 'mdi-form-select', keywords: 'template defaults custom fields data entry' },
        { id: 'pm', title: 'Preventative maintenance', icon: 'mdi-wrench-clock', keywords: 'pm maintenance plan steps complete close signature ratings guidance photos schedule meter usage reading hours lifespan wear curve dynamic nightly recompute' },
        { id: 'parts', title: 'Parts inventory', icon: 'mdi-package-variant-closed', keywords: 'parts stock aisle bin reserve reorder supplier inventory' },
        { id: 'contacts', title: 'Contacts & CRM', icon: 'mdi-card-account-details-outline', keywords: 'contacts crm vendor employee contractor work location supplier notes' },
        { id: 'assignments', title: 'Assignments (custody)', icon: 'mdi-account-switch-outline', keywords: 'assignment custody employee release traceability' },
        { id: 'alerts', title: 'Alerts & reminders', icon: 'mdi-bell-alert-outline', keywords: 'alerts reminders severity scan acknowledge dismiss email digest webhook teams microsoft servicenow' },
        { id: 'servicenow', title: 'ServiceNow integration', icon: 'mdi-cloud-sync-outline', keywords: 'servicenow incident ticket cmdb import sync connection' },
        { id: 'teams', title: 'Microsoft Teams', icon: 'mdi-microsoft-teams', keywords: 'teams microsoft chat channel webhook adaptive card messagecard alert digest notification workflow connector' },
        { id: 'admin', title: 'Administration', icon: 'mdi-cog-outline', keywords: 'admin users roles teams settings smtp email webhook workday configuration company companies password security lockout audit activity trail' },
        { id: 'companies', title: 'Companies (multi-company)', icon: 'mdi-domain', keywords: 'company companies multi tenant switch active dispose archive restore tax id federal state local entity access' },
        { id: 'security', title: 'Password & security · audit', icon: 'mdi-shield-key-outline', keywords: 'password policy complexity expiry lockout reuse history audit trail activity log change tracking export forced change' },
        { id: 'roles', title: 'Roles & permissions', icon: 'mdi-shield-account-outline', keywords: 'roles permissions admin finance operations viewer access' }
      ]
    };
  },
  computed: {
    filteredSections() {
      const needle = String(this.search || '').trim().toLowerCase();
      if (!needle) return this.sections;
      return this.sections.filter((s) =>
        s.title.toLowerCase().includes(needle) || s.keywords.includes(needle) || s.keywords.split(' ').some((k) => k.startsWith(needle))
      );
    }
  },
  watch: {
    modelValue(open) {
      if (open) {
        this.search = '';
        this.printing = false;
      }
    }
  },
  methods: {
    isShown(id) {
      return this.printing || this.active === id;
    },
    select(id) {
      this.active = id;
      this.$nextTick(() => {
        if (this.$refs.content) this.$refs.content.scrollTop = 0;
      });
    },
    print() {
      this.printing = true;
      this.$nextTick(() => {
        window.print();
        this.printing = false;
      });
    }
  }
};
</script>

<style scoped>
.manual-body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}
.user-manual-nav {
  flex: 0 0 264px;
  border-right: 1px solid rgba(var(--v-theme-on-surface), 0.12);
  overflow-y: auto;
  background: rgba(var(--v-theme-on-surface), 0.02);
}
.manual-content {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 28px 36px;
}
.manual-section {
  max-width: 820px;
}
.manual-section h2 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 0 0 14px;
  padding-bottom: 8px;
  border-bottom: 2px solid rgba(var(--v-theme-primary), 0.4);
}
.manual-section h3 {
  font-size: 1.08rem;
  font-weight: 700;
  margin: 22px 0 8px;
}
.manual-section p {
  line-height: 1.6;
  margin: 0 0 12px;
}
.manual-section ul,
.manual-section ol {
  line-height: 1.6;
  margin: 0 0 12px;
  padding-left: 22px;
}
.manual-section li {
  margin-bottom: 6px;
}
.manual-section a {
  color: rgb(var(--v-theme-primary));
  cursor: pointer;
}
.manual-callout {
  margin: 14px 0 18px;
}
.manual-table {
  width: 100%;
  border-collapse: collapse;
  margin: 6px 0 16px;
  font-size: 0.92rem;
}
.manual-table th,
.manual-table td {
  text-align: left;
  vertical-align: top;
  padding: 8px 12px;
  border-bottom: 1px solid rgba(var(--v-theme-on-surface), 0.12);
}
.manual-table th {
  font-weight: 700;
  background: rgba(var(--v-theme-on-surface), 0.04);
}
.manual-section :deep(code),
.manual-section code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(var(--v-theme-on-surface), 0.08);
}
.manual-code {
  margin: 6px 0 16px;
  padding: 14px 16px;
  border-radius: 8px;
  background: rgba(var(--v-theme-on-surface), 0.06);
  border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.82rem;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
}
.manual-doc-title h1 {
  font-size: 1.8rem;
  font-weight: 800;
  margin-bottom: 4px;
}
.manual-footer {
  margin-top: 32px;
  padding-top: 14px;
  border-top: 1px solid rgba(var(--v-theme-on-surface), 0.12);
  font-size: 0.85rem;
}
</style>
