/* ============================================================================
   Magic Tilt Team Portal — shared CHROME + COMPONENTS (single source of truth)
   ----------------------------------------------------------------------------
   The "Enterprise / Epicor Kinetic" look, hoisted out of 29 inline <style>
   blocks. team-theme.css owns the TOKENS (color, radius, shadow); this file
   owns the RULES that consume them. Nothing here invents a value — every
   color, radius and shadow resolves through a var() from team-theme.css. The
   only literal is `#fff` for text/icons sitting on a dark fill, where a token
   would be pure churn.

   REFERENCE IMPLEMENTATION: team-portal/resources.html. Its inline <style> is
   the standard this file was lifted from — 58px app bar with a 3px primary
   top rule, squared navy avatar, bordered white user chip, the .page-header
   command bar, flat cards with --shadow-sm and an `inset 3px 0 0 var(--primary)`
   hover rail, uppercase letterspaced micro-labels, Montserrat body /
   Titillium Web headings, html{font-size:14px}. Three deliberate additions the
   reference page lacks are marked [ADDED] below.

   HOW IT APPLIES: linked immediately AFTER css/team-theme.css, i.e. after every
   page's inline <style>. Chrome rules here are single-class (0,1,0), so equal
   specificity + later source order means they win over the page's legacy copy
   WITHOUT !important — a page's duplicate block can then simply be deleted.
   Token values still resolve from team-theme.css regardless of link order
   (custom properties are looked up at use time), and team-theme's !important
   .role-badge chips keep winning, so nothing about the cascade changes.

     fonts → team-sidebar.css → [page inline <style>] → team-theme.css
             → team-chrome.css → team-modal.css

   RULES OF THE HOUSE
     · NEVER style .modal / .modal-* / .csv-modal* / .status-modal* /
       .pdf-modal* / .audit-modal — css/team-modal.css owns that surface with
       36 !important declarations and will win regardless of order.
     · NEVER set .header z-index beyond the base, .header-top .logo margin, or
       anything else css/team-sidebar.css claims at (0,2,x) — it out-specifies
       this file no matter where it is linked.
     · DO NOT link this file on login.html or register.html. They are
       unauthenticated pages with no .header / .user-info / .main, a 16px root
       (every px on them was tuned against it) and a (0,2,1)
       `.login-header .logo img` this file cannot reach. They are exempt.
     · DO NOT link this file on dealer-portal pages: their .user-dropdown-menu
       is toggled by JS with an `.open` class rather than :hover.
     · Layout stays with the page. No grid-template, no position/z-index, no
       overflow except where a sticky app bar or a working dropdown genuinely
       requires it — each such line is commented with why.
     · Durations are literal, never var(--transition): 13 pages don't define
       that token and the ones that do disagree (.3s vs .2s). Canonical motion
       is .12s ease on the properties that actually change, never `all`.
     · Fonts go through var(--font-head, <literal>) — --font-head/--font-body
       are undefined on 14 pages and team-theme.css deliberately doesn't
       define them.

   COMPANION EDIT, REQUIRED WITH THE FIRST PAGE MIGRATION
     Canonical bar height is 3px + 58px + 1px = 62px. css/team-sidebar.css
     still declares `--sidebar-header-h: 70px` and hangs the nav drawer off it.
     Drop it to 62px in the same commit that first links this file, or the
     drawer floats 8px below the header on every migrated page.
   ============================================================================ */


/* ==========================================================================
   1. BASE  —  root scale, body type, reset
   Identical on all 27 chrome pages already; hoisted so a page's :root can be
   trimmed to just its font/spacing/transition tokens.
   ========================================================================== */

* { margin: 0; padding: 0; box-sizing: border-box; }

html { font-size: 14px; }   /* every px/rem in the portal is tuned against this */

body {
    font-family: var(--font-body, 'Montserrat', Helvetica, Arial, sans-serif);
    background: var(--bg);
    color: var(--text);
    /* min-height + column flex are the precondition for `.main { flex: 1 }`
       below (sticky-footer pattern). Verified identical on all 29 pages. */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

a { text-decoration: none; color: inherit; }


/* ==========================================================================
   2. TOP APP BAR
   ========================================================================== */

.header {
    background: var(--white);
    border-top: 3px solid var(--primary);       /* the signature Kinetic rule */
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    /* sticky + z-index are the component: an app bar that scrolls away or
       sits under the page is not an app bar. team-sidebar.css raises this to
       110 for `body.has-sidebar` at (0,2,1) — that rule wins, by design. */
    position: sticky;
    top: 0;
    z-index: 100;
}

/* max-width:none is load-bearing: it un-caps the four pages that pin the bar
   to 1600px. The bar is full-bleed even where the content column below is not. */
.header-inner { max-width: none; margin: 0 auto; padding: 0 20px; }

.header-top { display: flex; align-items: center; justify-content: space-between; height: 58px; }

.logo { display: flex; align-items: center; gap: 12px; }
/* must stay `.logo img` (0,1,1) — a bare `.logo` rule cannot reach the image */
.logo img { height: 36px; }
.logo-text { display: flex; flex-direction: column; line-height: 1.15; }
.logo-title {
    font-family: var(--font-head, 'Titillium Web', Helvetica, Arial, sans-serif);
    font-size: 14px;
    font-weight: 700;
    color: var(--ink);
}
.logo-subtitle {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--primary);
    font-weight: 700;
}

.header-right { display: flex; align-items: center; gap: 10px; }

/* .role-badge — background, color and border-radius belong permanently to
   team-theme.css, which sets them with !important. Only metrics are live here. */
.role-badge {
    padding: 5px 10px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.user-info {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 5px 12px 5px 5px;
    background: var(--white);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    /* [ADDED] resources.html has no account menu so it never needed these.
       15 pages hang an absolutely-positioned .user-dropdown-menu inside this
       chip; without position:relative the menu escapes to the nearest
       positioned ancestor and lands in the page corner. */
    position: relative;
    cursor: pointer;
}

/* `.user-avatar` is the same element under a legacy name on 12 pages. Shipping
   both selectors keeps this a CSS-only migration — the `id` attributes JS
   writes initials into (#user-avatar / #user-initials) are untouched. */
.user-avatar-sm,
.user-avatar {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);   /* squared, not 50% — 50% is for spinners and status dots */
    background: var(--navy);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 12px;
    flex-shrink: 0;
}

.user-name { font-size: 13px; font-weight: 600; color: var(--ink); }

/* --- account dropdown  [ADDED] -------------------------------------------
   Not in resources.html; this is a feature the standard is missing, not a
   divergence to delete. Derived from the customers.html variant — the only one
   with a working hover bridge — restyled onto tokens. position/z-index are
   what make an anchored menu an anchored menu. */
.user-dropdown-menu {
    position: absolute;
    top: 100%;
    right: 0;
    z-index: 200;
    min-width: 200px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    padding: 8px;
    /* load-bearing: this is the invisible hover bridge between chip and menu.
       The `top: calc(100% + 8px)` variants on three pages leave an 8px dead
       zone that drops the menu mid-travel — they converge onto this. */
    padding-top: 20px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity .12s ease, transform .12s ease, visibility .12s;
}
.user-info:hover .user-dropdown-menu,
.user-dropdown-menu.open {   /* .open = shim for any JS-toggled implementation */
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.user-dropdown-menu a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text);
}
.user-dropdown-menu a:hover { background: var(--primary-tint); color: var(--primary-dark); }
.user-dropdown-menu a svg { width: 15px; height: 15px; flex-shrink: 0; }
.user-dropdown-divider { border: none; border-top: 1px solid var(--border-subtle); margin: 4px 0; }


/* ==========================================================================
   3. CONTENT CONTAINER
   `flex: 1` works because body is a min-height:100vh column flex container
   (§1). Keep a page-local override AFTER this file for:
     · order-detail / pending-order-detail  max-width: 1200px
     · engineering-entry-detail             max-width: 1400px
     · part-master        display:flex; flex-direction:column; min-height:0
     · sales-order-backlog  flex:1; display:flex; flex-direction:column;
                            min-height:0; padding:0   (full-bleed iframe shell)
   parts.html and part-edit.html have no .main element at all — take the header
   chrome only, do not add one.
   ========================================================================== */

.main { max-width: none; margin: 16px auto 40px; padding: 0 20px; width: 100%; flex: 1; }


/* ==========================================================================
   4. PAGE HEADER — the command bar
   ⚠ .page-title and .page-subtitle are SCOPED to .page-header on purpose.
   Four pages (orders, reports, parts-daily-sales, shipping) put a bare
   .page-title inside a navy gradient .page-banner and paint it white. An
   unscoped `.page-title { color: var(--ink) }` here would win on source order
   and paint near-black text onto a navy banner — the title would vanish on
   four pages at once. Do not unscope these without converting those banners.
   ========================================================================== */

.page-header {
    background: var(--white);
    border: 1px solid var(--border);
    border-left: 4px solid var(--primary);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 14px 18px;
    margin-bottom: 16px;
}
.page-header .page-eyebrow {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--primary);
    font-weight: 700;
}
.page-header .page-title {
    font-family: var(--font-head, 'Titillium Web', Helvetica, Arial, sans-serif);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--ink);
    margin-top: 2px;
}
.page-header .page-subtitle { color: var(--text-muted); font-size: 13px; margin-top: 3px; }


/* ==========================================================================
   5. BUTTONS
   Base .btn is verbatim resources.html: uppercase, letterspaced, --radius-sm,
   transparent border, NO fill. A bare `class="btn"` is therefore a colourless
   surface — every button needs a modifier. audit-log.html and reports.html
   have bare .btn markup that renders filled today; add .btn-primary /
   .btn-ghost to that markup when their inline rules are deleted.
   ========================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
    padding: 9px 16px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-decoration: none;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.btn svg { width: 14px; height: 14px; flex-shrink: 0; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn:disabled,
.btn[disabled] { opacity: .6; cursor: default; pointer-events: none; transform: none; }

/* neutral outline — the workhorse secondary. .btn-secondary is an alias. */
.btn-ghost,
.btn-secondary { background: var(--white); border-color: var(--border-strong); color: var(--ink); }
.btn-ghost:hover,
.btn-secondary:hover { border-color: var(--primary); color: var(--primary); }

.btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); }

.btn-navy { background: var(--navy); border-color: var(--navy); color: #fff; }
.btn-navy:hover { background: var(--navy-mid); border-color: var(--navy-mid); }

.btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }

.btn-danger-ghost { background: var(--white); border-color: var(--border-strong); color: var(--danger); }
.btn-danger-ghost:hover { border-color: var(--danger); background: var(--danger-bg); }

/* amber section-bar action (verbatim resources.html .add-btn) */
.add-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: inherit;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--navy);
    background: var(--accent-bright);
    border: 0;
    padding: 7px 12px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.add-btn:hover { filter: brightness(.94); }
.add-btn svg { width: 14px; height: 14px; }
.add-btn--ghost { background: transparent; color: #fff; border: 1px solid var(--on-navy-border); }
.add-btn--ghost:hover { filter: none; background: var(--on-navy-fill); }
.add-btn[disabled] { opacity: .6; cursor: progress; filter: none; }

/* size modifiers — replace the ad-hoc .btn.sm / .btn-inline / .btn-action sizes */
.btn-sm { font-size: 11px; padding: 6px 11px; gap: 5px; }
.btn-sm svg { width: 12px; height: 12px; }
.btn-lg { font-size: 13px; padding: 12px 22px; }
/* opt-in touch target — preserves part-edit.html's deliberate 44px minimum
   without imposing it portal-wide */
.btn-touch { min-height: 44px; }

/* square icon button for table-row actions. The 30px box IS the component. */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--white);
    color: var(--ink);
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease;
}
.btn-icon:hover { border-color: var(--primary); color: var(--primary); }
.btn-icon svg { width: 14px; height: 14px; }


/* ==========================================================================
   6. CARDS / PANELS
   Geometry from resources.html .cat-card. The `inset 3px 0 0 var(--primary)`
   rail is the portal's hover signature — but ONLY for clickable cards; a
   static data panel must not lift, so the hover is opt-in via .is-interactive.
   No `overflow: hidden` here: it clips dropdowns and sticky table headers.
   Add it locally on cards with a flush image/iframe header.
   ========================================================================== */

.card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    transition: border-color .12s ease, box-shadow .12s ease;
}
.card.is-interactive,
.card--link { cursor: pointer; }
.card.is-interactive:hover,
.card--link:hover { border-color: var(--primary); box-shadow: inset 3px 0 0 var(--primary), var(--shadow); }

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 13px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-alt);
    border-radius: var(--radius) var(--radius) 0 0;
}
.card-title {
    font-family: var(--font-head, 'Titillium Web', Helvetica, Arial, sans-serif);
    font-size: 13px;
    font-weight: 700;
    color: var(--navy);
    text-transform: uppercase;
    letter-spacing: .04em;
    display: flex;
    align-items: center;
    gap: 8px;
}
.card-title svg { width: 16px; height: 16px; color: var(--primary); }
/* ⚠ highest-collision rule in this file: 8 pages already declare .card-body
   with a different padding (dashboard 8px, parts 14px, part-edit 20px). Those
   pages need `.card-body.flush` / `.card-body.tight`, or a local re-declare
   after this file, if their density is deliberate. */
.card-body { padding: 16px 18px; }
.card-body.flush { padding: 0; }
.card-body.tight { padding: 10px 12px; }
.card-actions { display: inline-flex; align-items: center; gap: 8px; }


/* ==========================================================================
   7. DATA TABLE PRIMITIVES
   Element-level on purpose: 15 pages already style tables exactly this way and
   every <table> in the portal is a data grid. Any page needing a different
   skin already scopes it (.fa-table thead th, #recent-orders-card thead th),
   which out-specifies these and is untouched.
   `width: 100%` is the one deliberate sizing property in this file — a data
   table that shrink-wraps its content is broken in every portal layout.
   `position: sticky` on frozen headers stays PER-PAGE: it only works inside
   that page's scroll container (.table-wrap max-height), so shipping it here
   would be inert at best and misleading at worst.
   ========================================================================== */

table { width: 100%; border-collapse: collapse; }

thead th {
    padding: 11px 16px;
    text-align: left;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .5px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
tbody tr { border-bottom: 1px solid var(--border); transition: background .12s ease; }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }
tbody td { padding: 13px 16px; font-size: 13px; color: var(--text); vertical-align: middle; }

/* density modifiers — replace the per-page cell-padding rewrites */
.table-compact thead th { padding: 9px 12px; font-size: 10.5px; }
.table-compact tbody td { padding: 9px 12px; font-size: 12.5px; }
.table-roomy thead th { padding: 11px 14px; }
.table-roomy tbody td { padding: 12px 14px; }

.th-sortable { cursor: pointer; user-select: none; }
.th-sortable:hover { color: var(--primary); }

.row-clickable { cursor: pointer; }
.row-clickable:hover td { background: var(--primary-wash); }
.td-right { text-align: right; }
.td-num { text-align: right; font-variant-numeric: tabular-nums; }


/* ==========================================================================
   8. STATUS CHIPS
   ⚠ DELIBERATE LOOK CHANGE: squared (--radius-sm), not the 12/20/999px
   lozenge 13 pages use today. resources.html's chips and team-theme.css's
   !important .role-badge are both squared; the lozenge is the single biggest
   visual inconsistency with the standard.
   ⚠ The ::before dot is ON by default (nominated canon). Pages that already
   declare `.status-badge.<state>::before { background: ... }` out-specify the
   currentColor default and keep their dot colour. Use .no-dot to suppress.
   ========================================================================== */

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    text-transform: uppercase;
    letter-spacing: .4px;
    white-space: nowrap;
}
.status-badge::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;   /* 50% is correct here and on spinners — nowhere else */
    flex-shrink: 0;
    background: currentColor;
}
.status-badge.no-dot::before { display: none; }

/* the union of every state vocabulary in the portal, collapsed onto four
   token pairs so one class means one colour everywhere */
.status-badge.active, .status-badge.open, .status-badge.shipped,
.status-badge.won, .status-badge.approved { background: var(--success-bg); color: var(--success); }

.status-badge.pending, .status-badge.pending_review, .status-badge.held,
.status-badge.submitted, .status-badge.processing { background: var(--caution-bg); color: var(--caution); }

.status-badge.inactive, .status-badge.rejected, .status-badge.failed,
.status-badge.cancelled, .status-badge.lost { background: var(--danger-bg); color: var(--danger); }

.status-badge.completed, .status-badge.closed, .status-badge.archived,
.status-badge.new { background: var(--light-gray); color: var(--gray-dark); }

/* solid classification pills */
.pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .4px;
    white-space: nowrap;
}
.pill-open { background: var(--success); color: #fff; }
.pill-held { background: var(--caution); color: #fff; }
.pill-trailer { background: var(--primary); color: #fff; }
.pill-parts { background: var(--gray-dark); color: #fff; }
.pill-closed { background: var(--border); color: var(--gray-dark); }

/* document-type tag (verbatim resources.html .flyer-thumb-tag) */
.type-tag {
    background: var(--pdf);
    color: #fff;
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: .09em;
    padding: 3px 7px;
    border-radius: 3px;
}


/* ==========================================================================
   9. FORM CONTROLS + FOCUS RING
   The canonical ring is var(--focus-ring) = 2px of --primary @18%. It retires
   four legacy recipes built on #006897 and #0265a1 — brand blues that no
   longer exist anywhere in team-theme.css — at 10-12% alpha, which was both
   off-palette and barely visible.
   ========================================================================== */

.form-label,
.field-label,
.field label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 5px;
}
.field-hint { font-size: 11px; color: var(--text-muted); margin-top: 5px; }

.form-input, .form-select, .form-textarea, .form-control, .control,
.field input[type=text] {
    font-family: inherit;
    font-size: 13px;
    color: var(--ink);
    padding: 9px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--white);
    transition: border-color .12s ease, box-shadow .12s ease;
}
/* block form fields fill their column; `.control` is deliberately EXCLUDED —
   it is a toolbar control and its pages size it with a local `.control.block`. */
.form-input, .form-select, .form-textarea, .form-control,
.field input[type=text] { width: 100%; }

.form-input:focus, .form-select:focus, .form-textarea:focus, .form-control:focus,
.control:focus, .field input[type=text]:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: var(--focus-ring);
}
.form-input::placeholder, .form-textarea::placeholder, .control::placeholder { color: var(--text-subtle); }
.form-input:disabled, .form-select:disabled, .form-textarea:disabled,
.form-control:disabled, .control:disabled { background: var(--surface-2); color: var(--gray); cursor: not-allowed; }
.form-textarea { min-height: 100px; resize: vertical; line-height: 1.45; }
.form-select, select.control { cursor: pointer; }

/* opt-in iOS zoom-on-focus guard. Safari zooms any focused control under
   16px; part-edit.html handles this deliberately and must keep it. Applied by
   adding .form-touch to the form/section, NOT globally. */
@media (max-width: 768px) {
    .form-touch .form-input,
    .form-touch .form-select,
    .form-touch .form-textarea { font-size: 16px; min-height: 44px; }
}

/* checkbox row (verbatim resources.html) — the !important here is inherited
   from the reference and is required to undo the uppercase micro-label rules
   above when a <label> wraps a checkbox. */
.field-check {
    display: inline-flex !important;
    align-items: center;
    gap: 8px;
    text-transform: none !important;
    letter-spacing: 0 !important;
    font-size: 13px !important;
    color: var(--text) !important;
    cursor: pointer;
    margin-bottom: 0 !important;
}
.field-check input { width: 15px; height: 15px; accent-color: var(--primary); cursor: pointer; }

/* inline error box (resources.html .res-error / .modal-error, tokenized) */
.form-error {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--danger);
    background: var(--danger-bg);
    border: 1px solid var(--danger-border);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
}


/* ==========================================================================
   10. EMPTY STATE
   `grid-column: 1 / -1` is layout, but it is inert outside a grid and every
   grid-hosted empty state in the portal requires it.
   ========================================================================== */

.empty-state {
    grid-column: 1 / -1;
    padding: 44px 20px;
    text-align: center;
    color: var(--text-muted);
    background: var(--white);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
}
/* borderless variants — these already sit inside a bordered card or table */
.table-empty,
.entries-empty {
    grid-column: 1 / -1;
    padding: 40px 20px;
    text-align: center;
    color: var(--text-muted);
}
.empty-state.flush { background: transparent; border: 0; }
.empty-state.dashed { border-style: dashed; }   /* preserves forms.html's deliberate dashed edge */

.empty-state svg,
.table-empty svg,
.entries-empty svg { width: 34px; height: 34px; color: var(--border-strong); margin-bottom: 10px; }

.empty-state-title,
.empty-state h3 {
    font-family: var(--font-head, 'Titillium Web', Helvetica, Arial, sans-serif);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    margin-bottom: 3px;
}
.empty-state-text,
.empty-state p { font-size: 12.5px; }

.list-empty { padding: 32px 16px; text-align: center; color: var(--text-muted); font-size: 13px; font-style: italic; }


/* ==========================================================================
   11. LOADING / SPINNER
   .spinner is declared on 21 of 29 pages and every declaration is already the
   same ring — only size and margin differ. Lowest-risk consolidation here.
   ========================================================================== */

.loading { padding: 48px 20px; text-align: center; color: var(--text-muted); font-size: 13px; }

.spinner {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 2px solid var(--border-strong);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    vertical-align: middle;
    margin-right: 8px;
}
@keyframes spin { to { transform: rotate(360deg); } }

.spinner-xs { width: 13px; height: 13px; vertical-align: -2px; }
.spinner-lg { display: block; width: 32px; height: 32px; border-width: 3px; margin: 0 auto 14px; vertical-align: baseline; }
/* on a filled --primary / --navy surface (in-button spinners) */
.spinner-on-dark { border-color: var(--on-navy-border); border-top-color: #fff; }


/* ==========================================================================
   12. BACK LINK  (verbatim resources.html; .btn-back / .back-btn are aliases)
   ========================================================================== */

.back-link, .btn-back, .back-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: inherit;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ink);
    margin-bottom: 14px;
    padding: 6px 12px;
    background: var(--white);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease;
}
.back-link svg, .btn-back svg, .back-btn svg { width: 14px; height: 14px; }
.back-link:hover, .btn-back:hover, .back-btn:hover { border-color: var(--primary); color: var(--primary); }


/* ==========================================================================
   13. RESPONSIVE CHROME
   part-edit.html has the best mobile app bar in the tree; it becomes the
   shared default. Everything else about responsive layout stays per-page.
   ========================================================================== */

@media (max-width: 768px) {
    .user-name { display: none; }
    .logo img { height: 32px; }
}

@media (max-width: 640px) {
    .header-inner { padding: 0 16px; }
    .main { padding: 0 16px; }
}

@media (max-width: 480px) {
    .logo-text { display: none; }
}
