/* ============================================================================
   clients.hostme.ie — WHMCS client portal
   Brand overlay for the STOCK WHMCS Twenty-One theme
   Draft v0.1 · not deployed

   WHERE THIS GOES
   ---------------
   /templates/twenty-one/css/custom.css

   NOT templates/six/. The install runs Twenty-One (verified: the fork at
   business/website/whmcs-theme/hostme-whmcs-2026/ is a byte-level copy of
   WHMCS 8.13.1 templates/twenty-one, 157 .tpl, 4 modified). The path written
   into `Client Portal Theme.dc.html` §1 and §2 is wrong for this install.

   Stock Twenty-One loads this file on its own. includes/head.tpl already
   carries `{assetExists file="custom.css"}` and oauth/layout.tpl carries the
   same, so the login/OAuth screens are covered too. NO .tpl file is edited to
   make this work — that is the whole point of the file.

   WHAT THIS FILE DOES NOT DO
   --------------------------
   - No dark mode, no toggle. Client Portal Theme.dc.html §1, verbatim:
     "Light. Nothing in this brand is dark."
   - No markup. The floating WhatsApp button (spec §2) needs one element on
     every page; that belongs in an `includes/hooks/` hook using
     ClientAreaFooterOutput, following the pattern already established in
     business/website/whmcs-hooks/. Its styling is section 14 below and is
     inert until that markup exists.
   - No copy. Interface strings (spec §3) go in lang/overrides/english.php.
   - No Cormorant Garamond. It is loaded on the marketing site as a display
     accent for hero accent words and card closing lines. The portal has no
     display tier, and Bible §17 bans the serif on invoice and quote surfaces
     outright. The token is declared below for parity and used nowhere.

   RULES THIS IMPLEMENTS
   ---------------------
   Website Build Rules §1 (tokens), §2 (purple identity / green conversation),
   §6 (action block), §8 (grounds, shape, motion);
   Brand Bible §17 (one green action per viewport, square cards, 6px buttons,
   motion spec, reduced-motion);
   Client Portal Theme.dc.html §1 (light, bordered cards, tabular figures,
   status colours).

   CONFLICT, RESOLVED DELIBERATELY — read before changing shape
   -----------------------------------------------------------
   Client Portal Theme.dc.html §1 asks for 8px cards and 999px pill buttons.
   Brand Bible §17 and Build Rules §8 say screen is square cards and 6px
   buttons, and handoff/tasks/04-website.md ranks the v2 rules ABOVE the
   portal doc where they disagree on "colour, corner or weight". This file
   follows §17. If Konrad wants the portal to keep pills, change section 5
   and nothing else — it is isolated there on purpose.
   ============================================================================ */


/* ==========================================================================
   0 · FONTS — self-hosted (Konrad, 10 Aug 2026)
   Same families the WordPress theme loads (functions.php), minus Cormorant.
   Served from res.hostme.ie, NOT Google Fonts: the portal is a payment
   surface and a webfont request to a third party from the card-entry page is
   exactly the exposure the open ePrivacy item in BLOCKED.md is about. Nothing
   here contacts a third-party host.

   These are the variable faces, so one file covers every weight in the range
   — 300–600 for Geist, 400–500 for Geist Mono. Do not add static weight
   files alongside them.

   Subsets are latin + latin-ext only, and the unicode-range values are
   copied verbatim from what Google serves, so the browser still downloads
   latin-ext only when a page actually needs it. Cyrillic, Vietnamese and the
   box-drawing symbols subset are deliberately not shipped; those code points
   fall back to Segoe UI.

   Both families are SIL OFL 1.1. The licence travels with the files —
   res.hostme.ie/font/OFL.txt. Do not remove it.
   ========================================================================== */

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url('https://res.hostme.ie/font/geist-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url('https://res.hostme.ie/font/geist-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('https://res.hostme.ie/font/geist-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('https://res.hostme.ie/font/geist-mono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ==========================================================================
   1 · TOKENS
   Canonical --hm-* names, copied from
   current/theme/hostme/assets/css/colors_and_type.css Part A so the portal and
   the website share one vocabulary. Do not rename these here — rename there.
   ========================================================================== */

:root {
  /* Ink and secondary text — §1 */
  --hm-ink:      #1A1A2E;
  --hm-ink-2:    #2E2C40;
  --hm-muted:    #5F5D75;
  --hm-faint:    #8B899E;
  --hm-hairline: rgba(26, 26, 46, 0.12);

  /* Identity. Purple is who; it never carries the message action. */
  --hm-purple:      #7C3AED;
  --hm-purple-text: #6D28D9;
  --hm-lilac:       #F5F1FB;

  /* Conversation. Green is where: action and chat, never identity.
     White text is legal on --hm-green-button and nowhere else. */
  --hm-green-button: #15803D;
  --hm-green-mark:   #22C55E;
  --hm-green-ground: #DCFCE7;
  --hm-green-ink:    #14532D;

  /* State. Nothing else uses these. */
  --hm-red:   #B91C1C;
  --hm-amber: #B45309;

  /* Grounds. Forest, sage and sand are web-band colours with no band in the
     portal — declared for parity, applied nowhere.

     REVIEWED 8 Aug 2026 against a late finding on the website side. Homepage
     v2 binds its dark grounds through a `forest` flag that DEFAULTS TO TRUE:

       const forest = (this.props.darkGround ?? 'forest') === 'forest';
       dark: forest ? '#123024' : '#1A1A2E'
       tint: forest ? '#E4EFE4' : '#EDE6F9'

     The literals in its var() fallbacks are the OTHER branch, so reading a
     colour off a fallback gives you the variant the design does not ship.
     That mistake was made once on the website and cost a full palette pass.

     It does not propagate here: the portal has no dark ground anywhere —
     every --hm-ink reference in this file is a text colour, never a
     background — so there is nothing to re-point. The site gained forest
     BANDS; the portal has bands nowhere, by design (Client Portal Theme §1,
     "Light. Nothing in this brand is dark."). The two are consistent, not
     divergent: site and portal chrome are both on --hm-page. */
  --hm-page:        #FBFAF9;
  --hm-forest:      #123024;
  --hm-forest-deep: #0C2119;
  --hm-sage:        #E4EFE4;
  --hm-sand:        #EDE7DD;

  /* Type */
  --hm-font:        'Geist', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --hm-font-mono:   'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  --hm-font-accent: 'Cormorant Garamond', Georgia, serif;  /* declared, unused */

  /* Shape — the PORTAL document's treatment, not Bible §17.
     Konrad's call, 8 Aug 2026: 8px cards and pill buttons in the portal.
     Client Portal Theme.dc.html §1 specifies 8px cards and 999px buttons;
     Bible §17 and Build Rules §8 specify square cards and 6px buttons for
     screen, and that is what the WEBSITE ships. The two surfaces therefore
     differ in shape on purpose — the site is square, the portal is soft.
     These three values are the only place that is decided. */
  --hm-radius:       8px;
  --hm-radius-btn:   var(--hm-radius-pill);
  --hm-radius-pill:  999px;

  /* Shadow. Cards are bordered, not filled — shadow appears on hover only. */
  --hm-shadow-sm: 0 1px 2px rgba(26, 26, 46, .06);
  --hm-shadow-md: 0 6px 16px rgba(26, 26, 46, .10);
  --hm-focus:     0 0 0 4px rgba(124, 58, 237, .22);

  /* Motion — Bible §17. One easing, three durations, nothing outside
     180–450ms. "Everything clickable moves. Nothing else does." */
  --hm-ease:      cubic-bezier(.2, .7, .2, 1);
  --hm-dur-fast:  200ms;
  --hm-dur:       260ms;
  --hm-dur-slow:  420ms;
}


/* ==========================================================================
   2 · PAGE AND BASE TYPE
   Twenty-One ships Open Sans through fontCssInclude and paints the body via
   .primary-bg-color. Both are overridden here rather than in the template.
   ========================================================================== */

html,
body,
body.primary-bg-color,
.main-body,
.main-content,
#main-body {
  background: var(--hm-page);
  color: var(--hm-ink-2);
}

body,
button,
input,
select,
textarea,
.btn,
.nav,
.navbar,
.card,
.list-group-item,
.table,
.form-control,
.dropdown-menu,
.modal {
  /* !important is load-bearing: Twenty-One's theme.min.css sets Open Sans at
     higher specificity on several of these. */
  font-family: var(--hm-font) !important;
}

body {
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.card-title,
.page-header h1 {
  font-family: var(--hm-font) !important;
  color: var(--hm-ink);
  font-weight: 600;
  letter-spacing: -0.03em;
}

/* No 800 tier in the portal. Bible §17 allows one 800 line per page and it is
   a marketing hero device; the portal has no hero. */

p { color: var(--hm-muted); }
small, .small, .text-muted { color: var(--hm-faint) !important; }


/* ==========================================================================
   3 · LINKS
   §2: ALL text links and small purple type are #6D28D9, never #7C3AED.
   Underline drops 4px over 200ms — Bible §17 motion.
   ========================================================================== */

a,
a:visited {
  color: var(--hm-purple-text);
  text-underline-offset: 2px;
  transition: color var(--hm-dur-fast) var(--hm-ease),
              text-underline-offset var(--hm-dur-fast) var(--hm-ease);
}

a:hover,
a:focus {
  color: var(--hm-purple-text);
  text-underline-offset: 6px;
}

a:focus-visible,
.btn:focus-visible,
.form-control:focus-visible {
  outline: none;
  box-shadow: var(--hm-focus);
}


/* ==========================================================================
   4 · MONO LABELS
   §1: Geist Mono for kickers, labels, phone numbers and any figure standing
   as a figure. Sizing follows the website theme's .eyebrow (11px / 0.16em),
   not Bible §04's paper spec (10px / 0.2em) — this is a screen surface.
   ========================================================================== */

.hm-kicker,
.card-subtitle,
.sidebar-menu-item-label,
.master-breadcrumb .breadcrumb,
.hm-breadcrumb .breadcrumb,
label,
.control-label,
th,
.table thead th {
  font-family: var(--hm-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--hm-muted);
}

/* Figures standing as figures: invoice numbers, IBANs, totals, stat tiles. */
code,
kbd,
pre,
.mono,
.invoice-number,
.stat,
.amount,
.price,
.invoice-total {
  font-family: var(--hm-font-mono);
}

/* Columns of money line up. Portal spec §1. */
.amount,
.price,
.invoice-total,
td.text-right,
th.text-right,
.table td.text-right,
.table th.text-right {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}


/* ==========================================================================
   5 · SHAPE — the isolated section
   Portal treatment (Konrad, 8 Aug 2026): cards, panels and inputs 8px;
   buttons pill; status pills, chips and avatars 999px.
   Every radius resolves from the three tokens in section 1. To move the
   portal onto the website's square/6px treatment instead, change ONLY those
   three — nothing in this section hard-codes a value.
   ========================================================================== */

.card,
.card-header,
.card-body,
.card-footer,
.card-sidebar,
.panel,
.well,
.alert,
.modal-content,
.list-group,
.list-group-item,
.dropdown-menu,
.form-control,
.custom-select,
.input-group-text,
.table,
.tile,
.invoice-container,
.outer-wrapper,
.inner-wrapper {
  border-radius: var(--hm-radius);
}

.btn,
.btn-sm,
.btn-lg,
.btn-xs,
.btn-block {
  border-radius: var(--hm-radius-btn);
}

.badge,
.label,
.chip,
.invoice-status,
.sidebar-menu-item-badge,
.rounded-circle,
.avatar {
  border-radius: var(--hm-radius-pill);
}

.hm-action-block {
  border-radius: 0 var(--hm-radius) var(--hm-radius) 0;
}


/* ==========================================================================
   6 · CARDS AND PANELS
   Portal spec §1: bordered, not filled. White card on the warm off-white page.
   ========================================================================== */

.card,
.panel,
.well,
.card-sidebar {
  background: #FFFFFF;
  border: 1px solid var(--hm-hairline);
  box-shadow: none;
}

.card-header,
.panel-heading {
  background: transparent;
  border-bottom: 1px solid var(--hm-hairline);
  color: var(--hm-ink);
  font-weight: 600;
}

.card-footer,
.panel-footer {
  background: transparent;
  border-top: 1px solid var(--hm-hairline);
}

/* Twenty-One paints accent stripes on the home cards from its own palette. */
.card-accent-blue,
.card-accent-green,
.card-accent-gold,
.card-accent-red,
.card-accent-orange {
  border-top: 2px solid var(--hm-purple);
}

/* Bible §17: cards lift 6px and deepen their shadow over 260ms.
   Only cards that are actually clickable — a static panel that moves is a lie. */
a > .card,
.card a.card-link,
.client-home-cards .card,
.tile {
  transition: transform var(--hm-dur) var(--hm-ease),
              box-shadow var(--hm-dur) var(--hm-ease);
}

a > .card:hover,
.client-home-cards .card:hover,
.tile:hover {
  transform: translateY(-6px);
  box-shadow: var(--hm-shadow-md);
}


/* ==========================================================================
   7 · BUTTONS — purple is the action, green is not
   Portal spec §1: "Primary action = purple. Never green."
   Build Rules §2: one green action per viewport, buttons only, and in the
   portal that one green thing is the WhatsApp bubble (section 14).

   Twenty-One ships .btn-success on ~20 controls across 10 templates — domain
   management, DNS, email forwarding, registrar lock, upgrades, transfer, add
   credit. Every one of them competes with the bubble for the single green
   slot, so they are all reassigned to purple. This is the single highest-value
   block in the file.
   ========================================================================== */

.btn {
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: background-color var(--hm-dur) var(--hm-ease),
              border-color var(--hm-dur) var(--hm-ease),
              transform var(--hm-dur-fast) var(--hm-ease),
              box-shadow var(--hm-dur) var(--hm-ease);
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary,
.btn-success,
.btn-info,
.btn-checkout,
.btn-cta {
  background-color: var(--hm-purple) !important;
  border-color: var(--hm-purple) !important;
  color: #FFFFFF !important;
}

.btn-primary:hover,  .btn-primary:focus,  .btn-primary:active,
.btn-success:hover,  .btn-success:focus,  .btn-success:active,
.btn-info:hover,     .btn-info:focus,     .btn-info:active,
.btn-checkout:hover, .btn-checkout:focus,
.btn-cta:hover,      .btn-cta:focus {
  background-color: var(--hm-purple-text) !important;
  border-color: var(--hm-purple-text) !important;
  color: #FFFFFF !important;
}

.btn-default,
.btn-secondary,
.btn-outline-primary {
  background: transparent;
  border: 1px solid var(--hm-purple);
  color: var(--hm-purple-text);
}

.btn-default:hover,
.btn-secondary:hover,
.btn-outline-primary:hover {
  background: var(--hm-lilac);
  border-color: var(--hm-purple);
  color: var(--hm-purple-text);
}

.btn-danger {
  background-color: var(--hm-red);
  border-color: var(--hm-red);
}

.btn-link { color: var(--hm-purple-text); }


/* ==========================================================================
   8 · STATE AND STATUS
   Portal spec §1, same meanings as everywhere else in the brand.
   ========================================================================== */

/* CORRECTED 10 Aug 2026, against the live portal.
   These were written as `.invoice-status.paid` — a COMPOUND selector, which
   needs both classes on one element. The real markup in viewinvoice.tpl is

       <div class="invoice-status"><span class="paid">Paid</span></div>

   so the state class is on a CHILD. The compound form never matched anything
   and the PAID badge was rendering in Twenty-One's own olive, on an otherwise
   branded invoice. Descendant selectors below — note the space.

   `.invoice-status.overdue` was wrong twice over: wrong combinator, and
   `overdue` is not one of the states this template emits. The real set is
   draft / unpaid / paid / refunded / cancelled / collections. All six are
   covered now, so no status can fall through to a framework default again. */

.label-success, .badge-success, .status-active, .alert-success,
.invoice-status .paid {
  background: var(--hm-green-ground) !important;
  color: var(--hm-green-ink) !important;
  border-color: var(--hm-green-ground) !important;
}

.label-danger, .badge-danger, .status-overdue, .alert-danger,
.invoice-status .collections {
  background: #FEE2E2 !important;
  color: var(--hm-red) !important;
  border-color: #FEE2E2 !important;
}

.label-warning, .badge-warning, .status-pending, .alert-warning,
.invoice-status .unpaid {
  background: #FEF3C7 !important;
  color: var(--hm-amber) !important;
  border-color: #FEF3C7 !important;
}

/* Draft, refunded and cancelled are all "no money is moving" states. They get
   the neutral treatment rather than a colour, because none of them is a
   problem the client has to act on. */
.invoice-status .draft,
.invoice-status .refunded,
.invoice-status .cancelled {
  background: var(--hm-lilac) !important;
  color: var(--hm-muted) !important;
  border-color: var(--hm-lilac) !important;
}

/* ADDED 10 Aug 2026, against the live portal, then widened the same day.

   `includes/panel.tpl` builds every panel header as
       card-title py-1 px-2 text-white font-weight-bold bg-{$type}
   so the colour is whatever Bootstrap utility the caller's `type` maps to.
   Two landed unstyled and both were caught on screen, not on disk:
     · the Ledger on every invoice — `bg-info`, teal #17a2b8
     · the Proposal on every quote — `bg-warning`, amber #ffc107

   Bootstrap's bg-* utilities carry !important, so ours needs !important AND
   more specificity: `.card-title.bg-warning` is two classes against
   `.bg-warning`'s one. Same trick forces the text back off `text-white`.

   Semantics are kept rather than flattened — a danger panel stays red,
   because a panel that has stopped meaning "error" is worse than an ugly one.
   Only the neutral types collapse to lilac. */
.card-title.bg-danger {
  background: #FEE2E2 !important;
  color: var(--hm-red) !important;
}

.card-title.bg-warning {
  background: #FEF3C7 !important;
  color: var(--hm-amber) !important;
}

.card-title.bg-success {
  background: var(--hm-green-ground) !important;
  color: var(--hm-green-ink) !important;
}

.bg-info,
.card-title.bg-info,
.card-title.bg-primary,
.card-title.bg-secondary,
.card-title.bg-default,
.card-title.bg-light,
.card-title.bg-dark {
  background: var(--hm-lilac) !important;
  color: var(--hm-ink) !important;
}

/* ==========================================================================
   8b · THE SWEEP — every remaining framework colour class
   Added 10 Aug 2026, and added SYSTEMATICALLY rather than one screenshot at
   a time, which is how the teal Ledger, the amber Proposal, the olive PAID
   and the purple WhatsApp label were each found.

   Method, so it can be repeated after any WHMCS upgrade: download the
   twenty-one templates at the matching tag, extract every
   `(bg|text|btn|alert|badge|label|border)-(primary|secondary|success|danger|
   warning|info|light|dark)` across all 174 files, and diff that set against
   this stylesheet. Nine classes were in the templates and not in here. All
   nine are below. Two of them were live defects, not cosmetic gaps:

     · `.close.text-light` in footer.tpl — the dismiss X on the shared modal.
       Bootstrap's text-light is #f8f9fa, which on a white modal body is a
       close button you cannot see.
     · `.text-success` in clientareadomains.tpl — a fa-check tick in raw
       Bootstrap green #28a745. Wrong green, on a page clients use.

   text-success maps to --hm-green-ink, NOT --hm-green-mark. #22C55E scores
   about 2.3:1 on white and fails WCAG AA for text; the ink green is legible
   and still unambiguously "good". The mark green stays for grounds.
   ========================================================================== */

.text-primary { color: var(--hm-purple-text) !important; }
.text-secondary { color: var(--hm-muted) !important; }
.text-success { color: var(--hm-green-ink) !important; }
.text-warning { color: var(--hm-amber) !important; }

/* Scoped to .close deliberately — text-light on a genuinely dark ground
   elsewhere should stay light. This is the invisible-X case only. */
.close.text-light { color: var(--hm-ink) !important; opacity: .75; }

/* A "warning" button is still an ACTION, and in this brand every action that
   is not the WhatsApp button is purple. Same treatment btn-success already
   gets in section 9 — green is never a portal control. */
.btn-warning {
  background-color: var(--hm-purple) !important;
  border-color: var(--hm-purple) !important;
  color: #FFFFFF !important;
}

.badge-secondary {
  background: var(--hm-lilac) !important;
  color: var(--hm-ink) !important;
}

.border-success { border-color: var(--hm-green-ground) !important; }
.border-light   { border-color: var(--hm-hairline) !important; }


/* The masthead on the invoice and quote pages is `<img src="{$logo}">` with no
   width, no height and no max-width, so it renders at whatever the uploaded
   file happens to be. logo-wordmark.png is 1206x288, which overflowed the
   container and put a horizontal scrollbar on every quote — the same failure
   Build Rules §7 calls out on the website.

   240px keeps the 4.19:1 wordmark at a document-masthead size (~57px tall).
   `height: auto` is what stops it distorting if the file is ever replaced at
   a different aspect ratio. */
.invoice-header img,
.invoice-container .invoice-header img {
  max-width: 240px;
  height: auto;
}

/* Belt and braces for everything else inside these standalone pages — no
   image should ever be able to widen the document. */
.invoice-container img {
  max-width: 100%;
  height: auto;
}

/* invoice.css sets `padding: 70px` on .invoice-container with no breakpoint.
   On a 390px phone that is 140px of chrome — 36% of the screen — leaving
   250px for the line items. Clients open invoices on phones far more often
   than on desktops, and every pay button in all 29 emails lands here.
   Nothing else about the layout changes; only the gutter. */
@media (max-width: 767.98px) {
  .invoice-container {
    padding: 24px;
    margin: 0 auto;
  }
}

.label-info, .badge-info, .alert-info,
.badge-primary, .label-primary {
  background: var(--hm-lilac) !important;
  color: var(--hm-purple-text) !important;
  border-color: var(--hm-lilac) !important;
}

.alert {
  border: 1px solid var(--hm-hairline);
}

/* Twenty-One's success card-header on a paid invoice is a full green bar with
   white text. Green never carries identity, and #22C55E-family greens fail
   contrast under white. Reassigned to the conversation ground. */
.card-header.bg-success {
  background: var(--hm-green-ground) !important;
  color: var(--hm-green-ink) !important;
}

.card-header.bg-success.text-white { color: var(--hm-green-ink) !important; }


/* ==========================================================================
   9 · HOME TILES
   clientareahome.tpl paints four stat tiles with .highlight.bg-color-blue /
   green / gold / red. Four unrelated hues on the first screen a client sees,
   one of which steals the green slot. All four become purple; the figures go
   mono via section 4.
   ========================================================================== */

.highlight.bg-color-blue,
.highlight.bg-color-green,
.highlight.bg-color-gold,
.highlight.bg-color-red,
.highlight.bg-color-orange {
  background: var(--hm-purple) !important;
}

.tile {
  background: #FFFFFF;
  border: 1px solid var(--hm-hairline);
}

.tile .stat { color: var(--hm-ink); font-weight: 500; }
.tile .title,
.tile i { color: var(--hm-muted); }


/* ==========================================================================
   10 · HEADER, NAV, SIDEBAR, FOOTER, BREADCRUMB
   Cosmetic only. Twenty-One's markup and its Bootstrap collapse behaviour are
   left exactly as shipped — that is what makes this file survive an update.
   ========================================================================== */

.header,
.navbar,
.main-navbar-wrapper,
.topbar {
  background: #FFFFFF;
  border-bottom: 1px solid var(--hm-hairline);
  box-shadow: none;
}

.navbar .nav-link,
.navbar-nav .nav-link {
  color: var(--hm-ink-2);
  font-weight: 500;
  transition: color var(--hm-dur-fast) var(--hm-ease);
}

.navbar .nav-link:hover,
.navbar-nav .nav-link:hover,
.navbar-nav .nav-item.active > .nav-link {
  color: var(--hm-purple-text);
}

.dropdown-menu {
  border: 1px solid var(--hm-hairline);
  box-shadow: var(--hm-shadow-md);
}

.dropdown-item:hover,
.dropdown-item:focus {
  background: var(--hm-lilac);
  color: var(--hm-purple-text);
}

.list-group-item {
  border-color: var(--hm-hairline);
  color: var(--hm-ink-2);
  transition: background-color var(--hm-dur-fast) var(--hm-ease);
}

.list-group-item-action:hover {
  background: var(--hm-lilac);
  color: var(--hm-purple-text);
}

.list-group-item.active {
  background: var(--hm-lilac);
  border-color: var(--hm-hairline);
  color: var(--hm-purple-text);
  font-weight: 600;
}

.master-breadcrumb {
  background: transparent;
  border-bottom: 1px solid var(--hm-hairline);
}

.master-breadcrumb .breadcrumb {
  background: transparent;
  padding-left: 0;
}

.footer {
  background: #FFFFFF;
  border-top: 1px solid var(--hm-hairline);
  color: var(--hm-faint);
}

.footer a { color: var(--hm-muted); }
.footer a:hover { color: var(--hm-purple-text); }

/* The registration line in the footer is a WHMCS setting, not CSS. It carries
   two [TBC] values (CRO number, VAT number) — see Client Portal Theme §4.
   Nothing is invented here. */


/* ==========================================================================
   11 · TABLES
   ========================================================================== */

.table {
  background: #FFFFFF;
  color: var(--hm-ink-2);
}

.table thead th {
  border-bottom: 1px solid var(--hm-hairline);
  border-top: none;
  color: var(--hm-muted);
}

.table td,
.table th {
  border-color: var(--hm-hairline);
}

.table-striped tbody tr:nth-of-type(odd) {
  background: var(--hm-page);
}

.table-hover tbody tr:hover {
  background: var(--hm-lilac);
}


/* ==========================================================================
   12 · FORMS
   Build Rules §9 form treatment, applied to the portal's own controls:
   ink labels, 1px rgba(26,26,46,.18) borders, 8px radius, purple focus ring,
   error text in #B91C1C.
   ========================================================================== */

.form-control,
.custom-select,
.input-group-text {
  background: #FFFFFF;
  border: 1px solid rgba(26, 26, 46, 0.18);
  border-radius: var(--hm-radius-btn);
  color: var(--hm-ink-2);
  transition: border-color var(--hm-dur-fast) var(--hm-ease),
              box-shadow var(--hm-dur-fast) var(--hm-ease);
}

.form-control:focus,
.custom-select:focus {
  border-color: var(--hm-purple);
  box-shadow: var(--hm-focus);
  outline: none;
}

.form-control::placeholder { color: var(--hm-faint); }

.has-error .form-control,
.is-invalid,
.form-control.is-invalid {
  border-color: var(--hm-red);
}

.invalid-feedback,
.help-block.text-danger,
.text-danger {
  color: var(--hm-red) !important;
}


/* ==========================================================================
   13 · THE ACTION BLOCK
   Build Rules §6. Lilac ground, 2px purple rule on the LEFT EDGE ONLY, square
   that edge and 8px the other three, mono kicker, no button inside it.
   One per page. Requires markup — inert until a hook or an override emits it.
   ========================================================================== */

.hm-action-block {
  background: var(--hm-lilac);
  border-left: 2px solid var(--hm-purple);
  padding: 20px 24px;
  margin: 24px 0;
}

.hm-action-block .hm-kicker { color: var(--hm-purple-text); }

.hm-action-block h2,
.hm-action-block h3 {
  margin: 6px 0 8px;
  font-size: 19px;
  line-height: 1.25;
}

.hm-action-block p {
  margin: 0;
  color: var(--hm-ink-2);
}

.hm-action-block strong { font-weight: 600; }

/* The panel is the instruction, not the control — §6 is explicit that there is
   no button inside it. */
.hm-action-block .btn { display: none; }


/* ==========================================================================
   14 · THE ONE GREEN ACTION
   Client Portal Theme §2: one floating WhatsApp button, bottom right, above
   everything. It is the ONLY green element in the portal — the pay button
   stays purple, because paying is not a conversation.

   Markup is NOT in this file and NOT in a .tpl. It belongs in
   includes/hooks/, on ClientAreaFooterOutput, following the pattern in
   business/website/whmcs-hooks/. These rules are inert until it exists.

   WHEN THAT HOOK IS WRITTEN, use the same inline WhatsApp mark the website
   uses — hostme_wa_icon() in the theme's functions.php. Not a lucide icon
   (lucide has no WhatsApp glyph), not a remote <img> (a third-party image
   request from a card-entry page, which is the exact thing open question Q5
   is about). Inline SVG, so the button cannot render blank if a CDN is slow.
   The rules below cover both an <img> and an inline <svg>.

   The website gates its floating button so it hides whenever another green
   action is on screen. No gate is needed here: this is the only green ACTION
   in the portal. The green-ground status pills are marks, not actions.

   White text is legal on #15803D and nowhere else.
   ========================================================================== */

.hm-msg {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 1050;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--hm-green-button);
  color: #FFFFFF;
  font-family: var(--hm-font);
  font-weight: 600;
  font-size: 15px;
  border-radius: var(--hm-radius-pill);
  padding: 13px 20px;
  text-decoration: none;
  box-shadow: 0 2px 12px rgba(26, 26, 46, 0.18);
  transition: transform var(--hm-dur) var(--hm-ease),
              box-shadow var(--hm-dur) var(--hm-ease);
}

/* :visited is NOT optional here, and it is not defensive coding — it is a bug
   that was live. Section 3 sets `a, a:visited { color: purple }` for the
   "every text link is #6D28D9" rule. `a:visited` scores (0,0,1,1); `.hm-msg`
   alone scores (0,0,1,0), so the moment anyone actually clicked the WhatsApp
   button the visited state won and repainted the label purple ON the green
   pill. It looks white until first use, which is exactly why it survived
   review — you cannot see this bug on a link you have never clicked.

   `.hm-msg:visited` is (0,0,2,0) and beats (0,0,1,1) on the class column, so
   no !important is needed. The inline SVG uses fill: currentColor and follows
   the label back to white on its own. */
.hm-msg:visited {
  color: #FFFFFF;
}

.hm-msg:hover,
.hm-msg:focus {
  color: #FFFFFF;
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(26, 26, 46, 0.22);
}

.hm-msg img,
.hm-msg svg {
  display: block;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* Build Rules §7 bug, same failure mode here: a fixed bubble covers content at
   the foot of the page. Give the footer clearance rather than hiding it. */
.footer { padding-bottom: 84px; }

/* Clients print invoices. A fixed bubble prints on top of one, and the footer
   clearance prints as a band of white space under it. Neither belongs on
   paper — the button is a screen action and paper has no conversation. */
@media print {
  .hm-msg { display: none; }
  .footer { padding-bottom: 0; }
}

/* The invoice-page line under the total — Client Portal Theme §2, second half.
   Also markup-dependent. */
.hm-msg-inline {
  display: block;
  margin-top: 12px;
  font-size: 15px;
  color: var(--hm-muted);
}

.hm-msg-inline a {
  color: var(--hm-green-button);
  font-weight: 600;
}


/* ==========================================================================
   15 · INVOICE AND QUOTE VIEWS
   The screens that matter most — every pay button in all 29 emails lands here.
   ========================================================================== */

.invoice-container,
.outer-wrapper,
.inner-wrapper {
  background: #FFFFFF;
  border-color: var(--hm-hairline);
}

.invoice-status {
  font-family: var(--hm-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 12px;
}

.invoice-total,
.invoice-container .total {
  color: var(--hm-ink);
  font-weight: 600;
}

/* Twenty-One prints a watermark for cancelled and draft invoices. */
.cancelled, .draft { color: var(--hm-faint); }


/* ==========================================================================
   16 · REMOVE WHMCS FURNITURE
   Client Portal Theme §4/§5: "Powered by WHMCompleteSolution" goes. It has no
   stable class in Twenty-One's markup, so this is a placeholder selector —
   confirm the real one against the rendered page before relying on it.
   Everything else on that list (language switcher, knowledgebase, tickets,
   downloads, status, announcements, self-registration) is a WHMCS SETTING,
   not CSS, and must not be hidden with display:none — hiding a live route
   leaves it reachable by URL.
   ========================================================================== */

/* .footer .powered-by { display: none; }  <-- selector unverified, left off */


/* ==========================================================================
   17 · MOTION — REDUCED
   Bible §17 makes this non-optional: prefers-reduced-motion turns every
   transition off and lands each element in its final position.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .btn:hover,
  a > .card:hover,
  .client-home-cards .card:hover,
  .tile:hover,
  .hm-msg:hover {
    transform: none;
  }
}


/* ==========================================================================
   18 · PRINT
   A client printing an invoice from the portal should get the paper brand:
   no fixed bubble, no chrome, ink on white.
   ========================================================================== */

@media print {
  .hm-msg,
  .hm-msg-inline,
  .header,
  .topbar,
  .navbar,
  .footer,
  .master-breadcrumb,
  .d-print-none {
    display: none !important;
  }

  html, body {
    background: #FFFFFF;
    color: var(--hm-ink);
  }

  .card, .panel {
    border: 1px solid var(--hm-hairline);
    /* Paper keeps 8px cards — Bible §17: "on paper, square corners read as
       unfinished." */
    border-radius: var(--hm-radius);
  }
}
