/* ============================================================================
   Hostika — WHMCS CLIENT AREA BRAND LAYER
   client/templates/hostika/css/custom.css
   ----------------------------------------------------------------------------
   WHAT THIS FILE IS

   `client/templates/hostika/` is a full copy of the stock `nexus` theme —
   all 253 files — with this file substituted for css/custom.css. It has to be
   a full copy: WHMCS 9.0.4 main themes do not support parent/child
   inheritance (`config: parent:` in theme.yaml is honoured only by
   WHMCS\View\Template\OrderForm, which overrides buildParent(); the Theme
   class does not, so getParent() returns NULL and resolveFilePath() has no
   fallback). A partial theme directory breaks. See theme.yaml.

   WHY custom.css AND NOT THE SCSS

   nexus ships sass/, but sass/theme.scss imports
   ../../../node_modules/bootstrap-four/scss/bootstrap and there is no
   node_modules, package.json or gulpfile anywhere in the tree. The SCSS is
   unbuildable and rebuilding it is not needed: includes/head.tpl loads
   all.min.css, then theme.min.css, then THIS file last, so plain cascade
   order is all the leverage required.

   MEASUREMENTS IN THIS FILE ARE MEASURED, NOT REMEMBERED

   Every count below was taken from this tree with grep, and every contrast
   ratio was computed with the WCAG 2.1 sRGB formula rather than eyeballed:

     var() references in css/theme.css ................ 392
     var() references across the whole nexus theme .... 1007
     distinct custom properties nexus/css/custom.css
       defines ........................................ 82
     of those 82, names nexus never actually reads .... 26
     border-radius declarations in css/theme.css ...... 316
       of which use a token ........................... 111
       of which are 0 / inherit ....................... 65
       HARDCODED, non-zero ............................ 140
     hardcoded non-zero radii in css/store.css ........ 31
     hardcoded non-zero radii in css/all.css .......... 32
     hardcoded non-zero radii in css/invoice.css ...... 101
     hardcoded "Open Sans" font stacks ................ 4  (2 in theme.css,
                                                            2 in store.css)
     Bootstrap literals under the nexus overlay:
       #007bff 34x   #28a745 28x   #17a2b8 17x
       #dc3545 28x   #ffc107 17x   #6c757d 37x

   HOW IT IS ORGANISED

     1. Self-hosted Inter (@font-face)
     2. --hk-* source tokens          <- the marketing site's palette
     3. The 82 stock nexus tokens, remapped onto --hk-*
     4. What tokens cannot reach — font stack, radii, the Bootstrap 4 colour
        layer, focus rings, touch targets
     5. The calm layer — the client area is a tool, not a pitch
     6. Panels emitted by includes/hooks/hostika_dashboard.php

   TEMPLATES EDITED (each one is a re-check on every WHMCS upgrade)

     header.tpl          — skip link; <html lang> driven by the active
                           language pack instead of hardcoded "en"; a class
                           hook on the no-logo fallback.
     includes/head.tpl   — preload the local Inter file; drop the Open Sans
                           stylesheet, which nothing renders in any more.

   Nothing else is edited. Everything else the brand needs is done here.

   TONE

   Calmer than hostika-bg.com on purpose. Same white ground, same ink type,
   same deep emerald — but emerald appears ONLY on primary actions, active
   states and success. Everything structural (chrome, dividers, table rules,
   card accents, "info" and "notice" states) collapses onto the neutral ramp.
   A customer opens this page to do a chore, not to be sold to.

   CONTRAST

   Target is AAA (7:1) for anything at body size, matching the marketing site.
   3:1 is the floor for large text and for non-text UI boundaries (1.4.11).
   Ratios are quoted against the surface the colour actually lands on.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   1. TYPEFACE — self-hosted Inter

   sass/_global.scss hardcodes `font-family: 'Open Sans', sans-serif`, which
   survives into css/theme.css twice (`body` and `.popover-user-notifications`)
   and into css/store.css twice more. Inter is not in client/assets/fonts/.

   The file is copied into this theme at assets/fonts/InterVariable.woff2
   (352 KB, SIL Open Font License, weights 100-900 in one variable file) so
   the theme directory is self-contained: copying templates/hostika/ to
   another WHMCS install carries its own typeface, and moving the client area
   to a different host needs no path edits.

   NOT hotlinked and NOT a Google Fonts request. The marketing site removed
   its third-party font request deliberately for privacy; reintroducing it
   here would leak every logged-in customer's page views to a third party.

   The url() is relative to THIS file, so it resolves wherever the install
   lives — no {$WEB_ROOT}, no absolute path, no Smarty.
   --------------------------------------------------------------------------- */

@font-face {
  font-family: 'InterVariable';
  font-style: normal;
  font-weight: 100 900;
  /* swap: text paints immediately in the fallback and re-renders when the font
     lands, rather than sitting invisible for the length of the download. */
  font-display: swap;
  src: url('../assets/fonts/InterVariable.woff2') format('woff2');
}

/* 'Inter' aliased to the same file, matching the marketing site's own
   @font-face, so a rule copied between the two projects resolves either way
   and neither name triggers a second download. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../assets/fonts/InterVariable.woff2') format('woff2');
}


/* ---------------------------------------------------------------------------
   2. --hk-* SOURCE TOKENS

   The marketing site's palette, read from assets/tokens-cool.css, namespaced
   so it cannot collide with the stock nexus names. The collision is real and
   would be silent: both files define --bg, --text, --success and --warning
   with DIFFERENT meanings. nexus's --bg is a CARD surface; the marketing
   site's --bg is the page ground.

   --hk-canvas is the one token with no direct counterpart in either source
   file. It is the ground BEHIND the cards (section#main-body), which the
   marketing site has no name for because it never stacks a card on a tinted
   band. Both values already exist in their palette: cool takes --bg-alt, warm
   takes --bg. Nothing is invented.

   The 11-step neutral ramp nexus wants is longer than either palette's grey
   steps. Steps with a Hostika equivalent use it; the gaps are marked INTERP
   and are the arithmetic midpoint of their neighbours. No INTERP value is
   ever assigned to a text token — they carry fills and lines only, so their
   sub-7:1 ratios never apply to copy.
   --------------------------------------------------------------------------- */

:root {
  /* --- COOL (active — mirrors assets/tokens-cool.css) --- */
  --hk-bg:            #ffffff;
  --hk-canvas:        #f6f7f9;   /* = tokens-cool --bg-alt */
  --hk-bg-cream:      #eceef2;
  --hk-bg-card:       #ffffff;
  --hk-ink:           #0b1018;

  --hk-text:          #0b1018;   /* 19.06:1 bg | 17.78:1 canvas | 16.41:1 cream — AAA */
  --hk-text-2:        #2f3540;   /* 12.32:1 bg | 11.50:1 canvas | 10.61:1 cream — AAA */
  --hk-text-mute:     #464d58;   /*  8.53:1 bg |  7.95:1 canvas |  7.34:1 cream — AAA */

  --hk-brand:         #047857;   /* 5.48:1 — FILL / BORDER / >=24px headings ONLY */
  --hk-brand-2:       #065f46;   /* hover step */
  --hk-brand-strong:  #065f46;   /* white ON this = 7.68:1 — AAA. Solid CTAs. */
  --hk-brand-light:   #34d399;   /* 9.92:1 on ink, 1.92:1 on white — DARK SURFACES ONLY */
  --hk-brand-soft:    #ecfdf5;   /* tint fill; --hk-brand-text on it = 10.20:1 — AAA */
  --hk-brand-text:    #044733;   /* 10.75:1 bg | 10.02:1 canvas — AAA. Body-size emerald. */

  --hk-accent:        #0b1018;   /* cool "accent" is ink, not amber — that is the variant */
  --hk-accent-soft:   #f3f4f6;   /* --hk-warn-text on it = 7.74:1 — AAA */

  --hk-warn:          #b45309;   /* 5.02:1 — fill / dot / border only */
  --hk-warn-text:     #7c3a06;   /*  8.52:1 bg — AAA */
  --hk-warn-strong:   #7c3a06;   /* white ON this = 8.52:1 — AAA */
  --hk-danger:        #b91c1c;   /* 6.47:1 — fill / dot / border only */
  --hk-danger-text:   #941313;   /*  8.89:1 bg — AAA */
  --hk-danger-strong: #941313;   /* white ON this = 8.89:1 — AAA */
  --hk-on-brand:      #ffffff;

  --hk-line:          #e2e5ea;   /* 1.26:1 — DECORATIVE hairline, never a control edge */
  --hk-line-2:        #c9ced6;   /* 1.58:1 — DECORATIVE heavier divider */
  --hk-line-strong:   #7c838f;   /* 3.82:1 bg | 3.56:1 canvas | 3.29:1 cream — meets
                                    1.4.11 on all three light surfaces. This is the
                                    ONLY grey allowed on a control boundary.
                                    (The earlier draft of this file carried #868d99
                                    here, which is 3.34:1 on white but 2.88:1 on
                                    --hk-bg-cream. tokens-cool.css has since darkened
                                    it; rate a border against the DARKEST surface it
                                    can land on, not the lightest.) */

  --hk-on-dark:             #ffffff;                  /* 19.06:1 on ink — AAA */
  --hk-on-dark-2:           rgba(255,255,255,0.82);   /* -> #d3d4d5, 12.84:1 — AAA */
  --hk-on-dark-mute:        rgba(255,255,255,0.62);   /* -> #a2a4a7,  7.63:1 — AAA */
  --hk-on-dark-line:        rgba(255,255,255,0.14);   /* -> #2d3138,  1.46:1 — decorative */
  --hk-on-dark-line-strong: rgba(255,255,255,0.38);   /* -> #686b70,  3.56:1 — meets 1.4.11 */
  --hk-on-dark-fill:        rgba(255,255,255,0.06);
  --hk-on-dark-fill-2:      rgba(255,255,255,0.12);

  --hk-focus:         #0b1018;   /* high-contrast dark ring, deliberately not the brand */
  --hk-focus-on-dark: #ffffff;
  --hk-focus-width:   3px;
  --hk-focus-offset:  2px;

  /* Radii — cool is the tight/enterprise variant, so the pair is 4/8.
     --hk-radius-sm is an ALIAS, not a fourth step: tokens-cool.css deleted the
     2px tier on the grounds that 2px and 4px are indistinguishable at any real
     viewing distance. It survives here only because section 4b groups
     Bootstrap's "sm" tier under that name, and because tokens-warm.css keeps
     the same alias. Delete both the day nothing spells it. */
  --hk-radius:        4px;
  --hk-radius-lg:     8px;
  --hk-radius-pill:   999px;
  --hk-radius-sm:     var(--hk-radius);

  /* Neutral ramp. 500 and 800 are INTERP — see the note above this block. */
  --hk-grey-50:   #f6f7f9;
  --hk-grey-100:  #eceef2;
  --hk-grey-200:  #e2e5ea;
  --hk-grey-300:  #c9ced6;
  --hk-grey-400:  #7c838f;
  --hk-grey-500:  #626974;   /* INTERP between 400 and 600 — fills/lines only */
  --hk-grey-600:  #464d58;
  --hk-grey-700:  #2f3540;
  --hk-grey-800:  #1d222c;   /* INTERP between 700 and 900 — fills/lines only */
  --hk-grey-900:  #0b1018;
  --hk-grey-950:  #0b1018;

  /* Type. Six static steps plus --hk-fs-meta, copied from tokens-cool.css:
     12 -> 14 -> 16 -> 18 -> 22 -> 36, whole pixels at a 16px root.
     --hk-fs-base is the FLOOR for anything a person reads on a phone;
     --hk-fs-sm is a desktop density step and is lifted to the floor at 600px
     at the foot of this section. --hk-fs-meta is the one sanctioned sub-16px
     size and is for metadata that is not reading matter. */
  --hk-fs-meta:  .75rem;     /* 12px */
  --hk-fs-sm:    .875rem;    /* 14px — becomes 16px at <=600px */
  --hk-fs-base:  1rem;       /* 16px */
  --hk-fs-lg:    1.125rem;   /* 18px */
  --hk-fs-xl:    1.375rem;   /* 22px */
  --hk-fs-2xl:   2.25rem;    /* 36px */
  /* Aliases, matching tokens-cool.css. They resolve THROUGH --hk-fs-sm, so
     the mobile lift below moves all of them with one declaration. */
  --hk-fs-3xs:   var(--hk-fs-sm);
  --hk-fs-2xs:   var(--hk-fs-sm);
  --hk-fs-xs:    var(--hk-fs-sm);
  --hk-fs-md:    var(--hk-fs-base);

  --hk-font-sans:  'InterVariable', 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --hk-font-serif: Georgia, "Times New Roman", serif;
  --hk-font-mono:  'SF Mono', Consolas, Monaco, monospace;

  --hk-lh-tight:  1.08;
  --hk-lh-snug:   1.15;
  --hk-lh-normal: 1.45;
  --hk-lh-body:   1.6;

  --hk-ls-tight: -0.03em;
  --hk-ls-snug:  -0.02em;
  --hk-ls-caps:   .14em;

  --hk-fw-normal:   400;
  --hk-fw-medium:   500;
  --hk-fw-semibold: 600;
  --hk-fw-bold:     700;

  --hk-sp-4:   4px;
  --hk-sp-8:   8px;
  --hk-sp-12: 12px;
  --hk-sp-16: 16px;
  --hk-sp-20: 20px;
  --hk-sp-24: 24px;
  --hk-sp-32: 32px;
  --hk-sp-40: 40px;
  --hk-sp-48: 48px;

  --hk-tap: 48px;   /* minimum touch target on every interactive element */
  --hk-t:   cubic-bezier(.2,.7,.2,1);

  /* Shadows. Cards in this theme are hairline-bordered with NO shadow, so
     these exist only for the two things that genuinely float above the page
     and need to say which layer they are on: the modal and the dropdown.
     Tokenised rather than typed inline because the warm palette uses a
     different pair, and a literal here would be left behind by a palette
     switch in exactly the way the radii would. */
  --hk-shadow-md: 0 4px 16px -6px rgba(11,16,24,0.10), 0 1px 3px rgba(11,16,24,0.06);
  --hk-shadow-lg: 0 14px 32px -14px rgba(11,16,24,0.18);

  /* Fifteen of the names in this block are not read by any rule below today:
     the four --hk-fs-* aliases, --hk-fs-xl, --hk-fw-normal, --hk-accent,
     --hk-bg, --hk-on-dark-fill, --hk-on-dark-fill-2, and the larger --hk-sp-*
     steps. They are kept deliberately.

     A scale is only usable if it is complete. The alternative — pruning to
     exactly what section 4 and 5 happen to reference this week — means the
     next person adding a panel finds --hk-sp-20 and --hk-sp-32 present but
     --hk-sp-24 missing, and types a literal. Half a scale is how the
     marketing site ended up with 31 ad-hoc spacing values in the first place.

     They also keep the cool and warm blocks symmetric, which is the property
     that makes a palette swap a one-attribute change. */
}

/* MOBILE TYPE FLOOR — the same mechanism tokens-cool.css uses.
   Raising --hk-fs-sm raises --hk-fs-3xs / -2xs / -xs with it, because custom
   property substitution uses the computed value on :root. One declaration,
   not the forty per-component overrides the marketing site used to carry.
   --hk-fs-meta is deliberately NOT lifted. 600px matches the breakpoint the
   marketing site switches layout at, so type and geometry step together. */
@media (max-width: 600px) {
  :root { --hk-fs-sm: var(--hk-fs-base); }
}

/* --- WARM (inert) — mirrors assets/tokens-warm.css -------------------------
   Everything below section 2 reads --hk-*, so switching the whole client area
   to the warm palette is this one block plus a single attribute. To enable:
   add data-hostika-palette="warm" to the <html> tag in header.tpl.
   Nothing else changes.

   Warm is the soft/linen variant: a tinted page ground rather than white, a
   real amber accent instead of cool's ink, and roughly double the radii
   (9/18 against 4/8). Its --hk-line-strong is #7a7157 — a warm grey, chosen
   in tokens-warm.css to clear 3:1 against ITS darkest light surface
   (--bg-cream #dfd5bf), not against white. Do not swap the two files'
   --line-strong values; each is rated against a different backdrop. */
:root[data-hostika-palette="warm"],
.hk-palette-warm {
  --hk-bg:            #f5f1ea;
  --hk-canvas:        #f5f1ea;   /* = tokens-warm --bg; warm has no white ground */
  --hk-bg-cream:      #dfd5bf;
  --hk-bg-card:       #ffffff;
  --hk-ink:           #0a0d14;

  --hk-text:          #0a0d14;
  --hk-text-2:        #373e4b;
  --hk-text-mute:     #434a55;

  --hk-brand:         #059669;
  --hk-brand-2:       #047857;
  --hk-brand-strong:  #065f46;
  --hk-brand-light:   #34d399;
  --hk-brand-soft:    #d1fae5;
  --hk-brand-text:    #044733;

  --hk-accent:        #b45309;   /* warm's accent IS amber */
  --hk-accent-soft:   #fbe9d2;

  --hk-warn:          #b45309;
  --hk-warn-text:     #632d05;
  --hk-warn-strong:   #7c3a06;
  --hk-danger:        #dc2626;
  --hk-danger-text:   #821010;
  --hk-danger-strong: #821010;

  --hk-line:          #dfd7c4;
  --hk-line-2:        #c7bf9f;
  --hk-line-strong:   #7a7157;

  --hk-focus:         #0a0d14;

  --hk-radius:        9px;
  --hk-radius-lg:    18px;

  --hk-grey-50:   #f5f1ea;
  --hk-grey-100:  #ebe5d6;
  --hk-grey-200:  #dfd7c4;
  --hk-grey-300:  #c7bf9f;
  --hk-grey-400:  #7a7157;
  --hk-grey-500:  #5e5949;   /* INTERP */
  --hk-grey-600:  #434a55;
  --hk-grey-700:  #373e4b;
  --hk-grey-800:  #21262f;   /* INTERP */
  --hk-grey-900:  #0a0d14;
  --hk-grey-950:  #0a0d14;

  --hk-shadow-md: 0 10px 30px -12px rgba(15,23,42,.18), 0 4px 8px -4px rgba(15,23,42,.08);
  --hk-shadow-lg: 0 25px 50px -20px rgba(5,150,105,.35);
}


/* ---------------------------------------------------------------------------
   3. THE 82 STOCK NEXUS TOKENS, REMAPPED

   Same names and the same order as nexus/css/custom.css, so a diff against a
   future WHMCS release shows exactly which tokens WHMCS added or dropped.

   Every one of the 82 is redeclared even where the value is unchanged. This
   file REPLACES the stock custom.css rather than adding to it, and theme.css
   makes 392 var() references: an undefined custom property resolves to the
   `unset` guaranteed-invalid value, not to a sane default, so a token dropped
   from this list paints nothing at all.

   26 of the 82 are defined by nexus and then never read anywhere in the
   theme: the whole --primary-50..950 ramp, --primary / --primary-lifted /
   --primary-accented, --secondary-lifted, --secondary-accented,
   --success-lifted, --warning-lifted, --info-lifted, --notice-accented,
   --error-accented, --neutral-950, --outline-sm/md/lg and
   --text-xs/sm/md/lg. They are kept and mapped anyway — a WHMCS point
   release or a third-party addon can start reading them without warning, and
   an unmapped one would then paint stock grey in the middle of a branded
   page.
   --------------------------------------------------------------------------- */

:root {
  --white: #fff;

  /* Neutral shades */
  --neutral-50:  var(--hk-grey-50);
  --neutral-100: var(--hk-grey-100);
  --neutral-200: var(--hk-grey-200);
  --neutral-300: var(--hk-grey-300);
  --neutral-400: var(--hk-grey-400);
  --neutral-500: var(--hk-grey-500);
  --neutral-600: var(--hk-grey-600);
  --neutral-700: var(--hk-grey-700);
  --neutral-800: var(--hk-grey-800);
  --neutral-900: var(--hk-grey-900);
  --neutral-950: var(--hk-grey-950);

  /* Primary ramp. Stock aliases these straight back to the neutral ramp; we
     point them at emerald so that if WHMCS ever starts reading --primary-N it
     gets the brand rather than grey. Only 600-800 are real brand steps — the
     tints above and shades below are the nearest honest thing in the palette,
     not interpolations invented for the purpose. */
  --primary-50:  var(--hk-brand-soft);
  --primary-100: var(--hk-brand-soft);
  --primary-200: var(--hk-brand-light);
  --primary-300: var(--hk-brand-light);
  --primary-400: var(--hk-brand);
  --primary-500: var(--hk-brand);
  --primary-600: var(--hk-brand);
  --primary-700: var(--hk-brand-2);
  --primary-800: var(--hk-brand-strong);
  --primary-900: var(--hk-brand-text);
  --primary-950: var(--hk-brand-text);

  /* Primary colors
     --brand-strong, not --brand: white on #065f46 is 7.68:1 (AAA), white on
     #047857 is 5.48:1 (AA only), and the primary button is the one control
     that must clear AAA. */
  --primary:          var(--hk-brand-strong);
  --primary-lifted:   var(--hk-brand);
  --primary-accented: var(--hk-brand-2);

  /* Secondary colors — graphite, never a second hue. */
  --secondary:          var(--hk-text-2);
  --secondary-lifted:   var(--hk-text-mute);
  --secondary-accented: var(--hk-text);

  /* Success colors
     One green in the whole product. Stock ships #00a63e, a different green
     from the brand emerald, which is exactly the sort of near-miss that makes
     a client area feel bolted onto the marketing site. */
  --success:          var(--hk-brand);
  --success-lifted:   var(--hk-brand-2);
  --success-accented: var(--hk-brand-text);

  /* Info colors
     Deliberately NOT blue. Royal blue was removed from this brand on purpose
     and stock's #155dfc would walk it straight back in through the tld-pricing
     chrome and every .text-info / .bg-info utility. Informational states read
     as graphite; the icon and the words carry the meaning. */
  --info:          var(--hk-text-2);
  --info-lifted:   var(--hk-text);
  --info-accented: var(--hk-text);

  /* Notice colors
     Stock is purple, and every use of it is decorative. Collapsed onto the
     neutral ramp — see TONE at the top: chrome does not get its own hue. */
  --notice:          var(--hk-line-strong);
  --notice-lifted:   var(--hk-text-mute);
  --notice-accented: var(--hk-text-2);

  /* Warning colors */
  --warning:          var(--hk-warn);
  --warning-lifted:   var(--hk-warn-strong);
  --warning-accented: var(--hk-warn-text);

  /* Error colors */
  --error:          var(--hk-danger);
  --error-lifted:   var(--hk-danger-strong);
  --error-accented: var(--hk-danger-text);

  /* Grayscale colors — --grayscale-lifted is the workhorse dark: 20 reads in
     theme.css and 5 more in invoice.css. */
  --grayscale:          var(--hk-text);
  --grayscale-lifted:   var(--hk-text-2);
  --grayscale-accented: var(--hk-text-mute);

  /* Neutral colors */
  --neutral:          var(--hk-text-mute);
  --neutral-lifted:   var(--hk-text-2);
  --neutral-accented: var(--hk-text);

  /* Text neutral colors
     --text-muted and --text-lifted collapse to the same value on purpose.
     Stock puts --text-muted at --neutral-400 (#9ca3af, 2.54:1 on white) and
     then uses it for real caption text 10 times in theme.css. Hostika has
     exactly one grey that clears 7:1 at body size, so both tiers get it.
     Losing a tier of visual hierarchy is the cheaper trade. */
  --text-inverted: var(--hk-on-brand);
  --text-muted:    var(--hk-text-mute);   /* 8.53:1 — AAA (stock: 2.61:1) */
  --text-lifted:   var(--hk-text-mute);
  --text-accented: var(--hk-text-2);
  --text:          var(--hk-text);

  /* Border neutral colors
     --border-muted and --border are DECORATIVE tiers (1.26:1 and 1.58:1) and
     are only ever used by nexus for card and panel edges — theme.css reads
     var(--border) three times, none of them on a control. Control boundaries
     are handled explicitly in section 4d and use --hk-line-strong. */
  --border-muted:    var(--hk-line);
  --border:          var(--hk-line-2);
  --border-lifted:   var(--hk-line-strong);   /* 3.82:1 — meets 1.4.11 */
  --border-accented: var(--hk-line-strong);

  /* Background neutral colors
     --bg is the CARD surface, --bg-lifted is the page canvas behind the cards
     (section#main-body), --bg-inverted is html/body and the footer. */
  --bg:          var(--hk-bg-card);
  --bg-muted:    var(--hk-canvas);
  --bg-lifted:   var(--hk-canvas);
  --bg-accented: var(--hk-bg-cream);
  --bg-inverted: var(--hk-ink);

  /* Additional colors
     Stock's decorative palette: gold, teal, emerald, pink. Only the
     .card-accent-* top borders and the .bg-color-* tile stripes consume them.
     Mapped onto brand and neutral so a dashboard cannot end up a crayon box. */
  --yellow-200:  var(--hk-accent-soft);
  --yellow-300:  var(--hk-warn);
  --teal-300:    var(--hk-brand);
  --teal-400:    var(--hk-brand-2);
  --emerald-300: var(--hk-brand);
  --pink-400:    var(--hk-line-strong);

  /* Font sizes
     Stock's four steps are 10px / 12px / 14px / 16px. 10px and 12px are below
     the readable floor and nexus never reads any of the four, so they are
     re-pointed at the Hostika scale rather than preserved: metadata, then the
     small step, then the small step again, then the body floor. */
  --text-xs: var(--hk-fs-meta);   /* 12px — metadata only */
  --text-sm: var(--hk-fs-sm);     /* 14px, 16px on phones */
  --text-md: var(--hk-fs-sm);
  --text-lg: var(--hk-fs-base);   /* 16px */

  /* Outline widths (stock's naming — these are px widths, not colours) */
  --outline-sm: 1px;
  --outline-md: 2px;
  --outline-lg: var(--hk-focus-width);

  /* Rounding — the three names nexus actually uses.
     --rounding-md is read 95x in theme.css and 215x across the theme (cards,
     buttons, inputs); --rounding-sm 50x / 111x; --rounding-lg 5x / 11x.
     Pointing these three at the tokens is what makes a palette switch move
     the geometry as well as the colour. */
  --rounding-sm: var(--hk-radius-sm);
  --rounding-md: var(--hk-radius);
  --rounding-lg: var(--hk-radius-lg);

  /* Other
     --disabled-opacity raised from stock's 25%: disabled controls are exempt
     from 1.4.3, but at a quarter opacity a disabled "Pay now" button is not
     readable enough to tell the customer WHY they cannot press it. */
  --letter-spacing: 0em;
  --disabled-opacity: 45%;
}


/* ---------------------------------------------------------------------------
   4. WHAT TOKENS DO NOT REACH

   theme.css is Bootstrap 4.5.3 with a nexus overlay on top. The overlay uses
   var(); the ~9,000 lines of Bootstrap underneath do not. Everything in this
   section exists because there is no token to turn.
   --------------------------------------------------------------------------- */

/* 4a. FONT STACK
   Four hardcoded "Open Sans" declarations survive from sass/_global.scss:

     css/theme.css  body
     css/theme.css  .popover-user-notifications
     css/store.css  .landing-page.sitelockvpn .hero h2
     css/store.css  .landing-page.threesixtymonitoring

   plus Bootstrap's own system stack on `body`, `.btn`, `.form-control` and
   friends. All of them are plain-specificity rules in files that load before
   this one, so matching their selectors is enough — no !important anywhere in
   this block.

   includes/head.tpl no longer loads open-sans-family.css at all (see the
   TEMPLATES EDITED note at the top), so the four rules above now fall through
   to the generic `sans-serif` if this block ever fails to match. They are
   listed individually rather than covered by a `*` selector precisely so that
   a WHMCS upgrade which renames one shows up as a visibly wrong font rather
   than as nothing. */
body,
.popover-user-notifications,
.landing-page.sitelockvpn .hero h2,
.landing-page.threesixtymonitoring,
.btn,
.form-control,
.custom-select,
input, select, textarea, button, optgroup {
  font-family: var(--hk-font-sans);
}

body {
  font-size: var(--hk-fs-base);
  line-height: var(--hk-lh-body);
  color: var(--hk-text);            /* 19.06:1 on white — AAA */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Body copy floor. Bootstrap sets 1rem on body but nexus drops several
   regions to 14px and the sidebar below that; on a phone that is 14px of
   Cyrillic, which is the most common single complaint about stock WHMCS.
   These regions keep their relative rank at desktop widths and simply stop
   shrinking below the floor. */
@media (max-width: 600px) {
  body,
  .sidebar .list-group-item,
  .card-body,
  .card-text,
  .table,
  .table td,
  .table th,
  .form-control,
  .custom-select,
  .btn,
  .nav-link,
  .dropdown-item,
  .list-group-item,
  .breadcrumb,
  small, .small {
    font-size: var(--hk-fs-base);
  }
}

/* Headings pick up the marketing site's tight tracking. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.card-title, .pricing-card-title {
  font-family: var(--hk-font-sans);
  font-weight: var(--hk-fw-bold);
  letter-spacing: var(--hk-ls-snug);
  line-height: var(--hk-lh-snug);
  color: var(--hk-text);
}
h1, .h1 {
  letter-spacing: var(--hk-ls-tight);
  line-height: var(--hk-lh-tight);
}

/* The Georgia italic accent word, so the client area speaks the same headline
   language as the marketing site. Applied by wrapping one word in
   <em class="hk-accent">. Georgia is a system font on every target platform,
   so this costs no bytes. */
.hk-accent {
  font-family: var(--hk-font-serif);
  font-style: italic;
  font-weight: var(--hk-fw-medium);
  letter-spacing: var(--hk-ls-snug);
}

/* Money lines up when the numerals are tabular, and a client area is mostly
   columns of money. Inter ships tabular figures in the variable file. */
.table td, .table th,
.invoice-items, .amount, .price, .hk-allowance-figure {
  font-variant-numeric: tabular-nums;
}

code, kbd, pre, samp { font-family: var(--hk-font-mono); }


/* 4b. RADII
   140 hardcoded non-zero border-radius declarations in theme.css, 31 in
   store.css, 32 in all.css — none tokenised. They are Bootstrap's
   0.2rem / 0.25rem / 0.3rem / 0.5rem / 1rem / 10rem / 50rem and the order
   form's 8px family. Grouped below by which of the three Hostika radii they
   should become, so that switching to the warm palette (4/8 -> 9/18) moves
   all of them together instead of leaving Bootstrap's geometry behind.

   Note that cool's 4px happens to equal Bootstrap's 0.25rem, so on the ACTIVE
   palette most of this block is a no-op you cannot see. It is not redundant:
   it is the difference between a palette switch working and a palette switch
   half-working.

   invoice.css's 101 hardcoded radii are deliberately NOT remapped. That file
   styles the print/PDF invoice view, which is governed by
   whmcs-pdf/invoicepdf.tpl and Bulgarian фактура convention rather than by
   this brand layer. */

/* -> --hk-radius (the 0.25rem / 0.2rem / 0.3rem workhorse) */
.img-thumbnail, .form-control, .custom-select, .custom-file,
.custom-file-label, .valid-tooltip, .invalid-tooltip,
.btn, .dropdown-menu, .input-group-text, .card, .alert,
.list-group, .toast, .nav-pills .nav-link,
.page-link, .progress, .badge, .jumbotron, .modal-content,
.popover, .tooltip-inner, .custom-switch .custom-control-label::before,
.card-img-overlay, .rounded {
  border-radius: var(--hk-radius);
}

/* Corner-specific radii stay corner-specific. Bootstrap rounds only the outer
   corners of these; giving them all four detaches a list item from its group
   and puts a rounded lip on the bottom of every tab. */
.list-group-item:first-child, .card-header:first-child, .toast-header,
.nav-tabs .nav-link, .modal-header {
  border-radius: var(--hk-radius) var(--hk-radius) 0 0;
}
.list-group-item:last-child, .card-footer:last-child, .modal-footer {
  border-radius: 0 0 var(--hk-radius) var(--hk-radius);
}

/* -> --hk-radius-sm. On cool this is an alias of --hk-radius, so the tier is
   currently invisible; it is kept as a separate rule because warm may split
   them again and because .btn-xs already reads var(--rounding-sm). */
kbd, .form-control-sm, .btn-sm, .btn-group-sm > .btn, .btn-xs,
.btn-group-xs > .btn, .custom-control-label::before,
.input-group-sm > .form-control,
.input-group-sm > .custom-select,
.input-group-sm > .input-group-prepend > .input-group-text,
.input-group-sm > .input-group-append > .input-group-text,
.input-group-sm > .input-group-prepend > .btn,
.input-group-sm > .input-group-append > .btn,
.rounded-sm {
  border-radius: var(--hk-radius-sm);
}

/* -> --hk-radius-lg (Bootstrap's "lg" tier, plus the things that frame) */
.form-control-lg, .btn-lg, .btn-group-lg > .btn,
.input-group-lg > .form-control,
.input-group-lg > .custom-select,
.input-group-lg > .input-group-prepend > .input-group-text,
.input-group-lg > .input-group-append > .input-group-text,
.input-group-lg > .input-group-prepend > .btn,
.input-group-lg > .input-group-append > .btn,
.rounded-lg {
  border-radius: var(--hk-radius-lg);
}

/* Genuine pills stay pills. A pill is a SHAPE, not a step on the scale, which
   is why 999px is a token of its own and why 50% is not used anywhere: every
   element it was on is square, where 999px renders the identical circle. */
.badge-pill, .rounded-pill, .rounded-circle,
.custom-range::-webkit-slider-thumb,
.custom-range::-moz-range-thumb,
.custom-range::-ms-thumb {
  border-radius: var(--hk-radius-pill);
}
.custom-range::-webkit-slider-runnable-track,
.custom-range::-moz-range-track,
.custom-range::-ms-fill-lower,
.custom-range::-ms-fill-upper {
  border-radius: var(--hk-radius-sm);
}

/* The order form's 8px family. theme.css carries 120 #order-standard_cart
   rules; these are compound radii on joined controls — an input welded to an
   addon, a tab welded to its panel — so each corner has to be named
   individually or the seam reopens. */
body #order-standard_cart .field,
body #order-standard_cart .form-control,
body #order-standard_cart .panel,
body #order-standard_cart .card,
.primary-content .card.kb-category,
.intl-tel-input .country-list {
  border-radius: var(--hk-radius);
}
body #order-standard_cart .panel .panel-heading,
body #order-standard_cart .secondary-cart-body .view-cart-tabs .nav-tabs a[aria-expanded="true"] {
  border-radius: var(--hk-radius) var(--hk-radius) 0 0;
}
body #order-standard_cart .panel .panel-footer,
body #order-standard_cart .domain-pricing .featured-tld .price {
  border-radius: 0 0 var(--hk-radius) var(--hk-radius);
}
body #order-standard_cart .domain-pricing .tld-pricing-header .tld-column {
  border-radius: var(--hk-radius) 0 0 var(--hk-radius);
}
body #order-standard_cart .domain-pricing .tld-pricing-header .col-md-8,
body #order-standard_cart .domain-pricing .tld-pricing-header div:last-child {
  border-radius: 0 var(--hk-radius) var(--hk-radius) 0;
}

/* :has() lives in rules of its OWN, never in a comma list with anything else.
   A selector list containing one selector a browser cannot parse invalidates
   the WHOLE rule, so mixing these in above would silently drop the plain
   selectors too on any engine without :has(). */
body #order-standard_cart .domain-pricing .tld-pricing-header:has(~ .filtered-row) {
  border-radius: var(--hk-radius) var(--hk-radius) 0 0;
}
body #order-standard_cart .input-group:has(.input-group-addon) .input-group-addon {
  border-radius: var(--hk-radius) 0 0 var(--hk-radius);
}
body #order-standard_cart .input-group:has(.input-group-addon) .form-control {
  border-radius: 0 var(--hk-radius) var(--hk-radius) 0;
}
body #order-standard_cart .domain-checker-container .input-group:not(:has(.input-group-addon)) .form-control {
  border-radius: var(--hk-radius);
}


/* 4c. THE BOOTSTRAP COLOUR LAYER
   34 uses of #007bff, 28 of #28a745, 17 of #17a2b8, 28 of #dc3545 and 17 of
   #ffc107 sit under the nexus overlay. The overlay repaints `a`,
   `.btn-primary` and `.btn-default` and leaves everything else Bootstrap
   blue: outline buttons, badges, pills, pagination, progress bars,
   list-group active states, custom checkboxes, the .text- / .bg- / .border-
   utilities, and every alert. Royal blue is gone from this brand; it does not
   get back in here.

   Note for whoever edits these comments next: never write a CSS class glob as
   `.text-*` immediately followed by a slash. The `*` and `/` form a comment
   terminator, the comment ends early, and the rest of the sentence becomes
   invalid CSS that silently eats the next rule. That is exactly what happened
   in the first draft of this block. */

.btn-primary,
.btn-primary:disabled,
.btn-primary.disabled {
  color: var(--hk-on-brand);
  background-color: var(--hk-brand-strong);   /* white on it = 7.68:1 — AAA */
  background-image: none;                     /* no gradients in the client area */
  border-color: var(--hk-brand-strong);
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show > .btn-primary.dropdown-toggle {
  color: var(--hk-on-brand);
  background-color: var(--hk-brand-text);     /* darkens on press — 10.75:1 */
  border-color: var(--hk-brand-text);
}

.btn-outline-primary,
.btn-outline-primary:disabled,
.btn-outline-primary.disabled {
  color: var(--hk-brand-text);                /* 10.75:1 — AAA at label size */
  background-color: transparent;
  border-color: var(--hk-brand);              /* 5.48:1 — clears 3:1 for a boundary */
}
.btn-outline-primary:hover,
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active,
.show > .btn-outline-primary.dropdown-toggle {
  color: var(--hk-on-brand);
  background-color: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
}

/* .btn-success is WHMCS's "pay this invoice" control in several templates, so
   it stays a distinct, confident button — but it is the same emerald, not
   Bootstrap's #28a745. */
.btn-success,
.btn-success:disabled,
.btn-success.disabled {
  color: var(--hk-on-brand);
  background-color: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
}
.btn-success:hover,
.btn-success:focus,
.btn-success:not(:disabled):not(.disabled):active,
.btn-success:not(:disabled):not(.disabled).active {
  color: var(--hk-on-brand);
  background-color: var(--hk-brand-text);
  border-color: var(--hk-brand-text);
}

.btn-danger, .btn-danger:disabled, .btn-danger.disabled {
  color: var(--hk-on-brand);
  background-color: var(--hk-danger-strong);  /* white on it = 8.89:1 — AAA */
  border-color: var(--hk-danger-strong);
}
.btn-danger:hover,
.btn-danger:not(:disabled):not(.disabled):active {
  color: var(--hk-on-brand);
  background-color: var(--hk-danger-text);
  border-color: var(--hk-danger-text);
}

/* Stock .btn-warning is #ffc107 with #212529 text. The amber/near-black pair
   is legible but reads as a caution triangle on a page that is mostly
   billing. Kept as the darkened amber so it stays a warning without shouting,
   and so its label clears AAA rather than scraping AA. */
.btn-warning, .btn-warning:disabled, .btn-warning.disabled {
  color: var(--hk-on-brand);
  background-color: var(--hk-warn-strong);    /* white on it = 8.52:1 — AAA */
  border-color: var(--hk-warn-strong);
}

.btn-info {
  color: var(--hk-on-brand);
  background-color: var(--hk-text-2);         /* white on it = 12.32:1 — AAA */
  border-color: var(--hk-text-2);
}

/* The default/secondary button is the one most customers press most often
   (Back, Cancel, View details). Its border IS its affordance, so it uses the
   only grey that clears 1.4.11. */
.btn-secondary, .btn-default {
  color: var(--hk-text);
  background-color: var(--hk-bg-card);
  border-color: var(--hk-line-strong);        /* 3.82:1 on white — meets 1.4.11 */
}
.btn-secondary:hover, .btn-default:hover,
.btn-secondary:not(:disabled):not(.disabled):active,
.btn-default:not(:disabled):not(.disabled):active {
  color: var(--hk-on-brand);
  background-color: var(--hk-text-2);
  border-color: var(--hk-text-2);
}

.btn-link { color: var(--hk-brand-text); }
.btn-link:hover { color: var(--hk-brand-text); text-decoration: underline; }

/* Links inside prose. The nexus overlay sets `a { color: var(--text) }` — ink
   — which is calm but leaves nothing except position to say "this is a link".
   Underline them and give them the AAA emerald: that is the accessible
   answer (1.4.1, colour is never the only cue) and it keeps the page from
   turning into a field of coloured words. */
.card-body a:not(.btn):not(.list-group-item):not(.nav-link):not(.dropdown-item),
.card-text a:not(.btn),
p a:not(.btn),
.alert a:not(.btn) {
  color: var(--hk-brand-text);                /* 10.75:1 — AAA at body size */
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.card-body a:not(.btn):hover,
.card-text a:not(.btn):hover,
p a:not(.btn):hover {
  text-decoration-thickness: 2px;
}

.badge-primary   { background-color: var(--hk-brand-strong);  color: var(--hk-on-brand); }
.badge-success   { background-color: var(--hk-brand-strong);  color: var(--hk-on-brand); }
.badge-info      { background-color: var(--hk-text-2);        color: var(--hk-on-brand); }
.badge-warning   { background-color: var(--hk-warn-strong);   color: var(--hk-on-brand); }
.badge-danger    { background-color: var(--hk-danger-strong); color: var(--hk-on-brand); }
.badge-secondary { background-color: var(--hk-text-mute);     color: var(--hk-on-brand); }
.badge-dark      { background-color: var(--hk-ink);           color: var(--hk-on-brand); }
.badge-light     { background-color: var(--hk-bg-cream);      color: var(--hk-text); }
a.badge-primary:hover, a.badge-primary:focus { background-color: var(--hk-brand-text); }

/* Alerts. Bootstrap's tinted-background + tinted-text pairs land between 4:1
   and 6:1, i.e. AA at best. Rebuilt as: white ground, hairline border, a 3px
   status rule down the leading edge, ink text at 19:1. Also much quieter,
   which is the point — a client area shows a lot of alerts. */
.alert {
  background-color: var(--hk-bg-card);
  border: 1px solid var(--hk-line);
  border-left: 3px solid var(--hk-line-strong);
  color: var(--hk-text);                      /* 19.06:1 — AAA */
}
.alert-primary, .alert-success { border-left-color: var(--hk-brand); }
.alert-info                    { border-left-color: var(--hk-text-2); }
.alert-warning                 { border-left-color: var(--hk-warn); }
.alert-danger                  { border-left-color: var(--hk-danger); }
.alert-primary, .alert-success, .alert-info,
.alert-warning, .alert-danger, .alert-secondary, .alert-dark, .alert-light {
  color: var(--hk-text);
}
.alert .alert-link { color: var(--hk-brand-text); text-decoration: underline; }
/* The status word must not be carried by the 3px rule alone (1.4.1). WHMCS
   puts an <i class="fa*"> in most alerts already; where it does not, the
   heading text says which kind it is. */
.alert .fa, .alert .fas, .alert .far, .alert .fal, .alert .fad { color: inherit; }

/* Contextual table rows: tint only, never a coloured text pair. */
.table-primary, .table-primary > th, .table-primary > td,
.table-success, .table-success > th, .table-success > td { background-color: var(--hk-brand-soft); }
.table-warning, .table-warning > th, .table-warning > td  { background-color: var(--hk-accent-soft); }
.table-info,    .table-info > th,    .table-info > td     { background-color: var(--hk-canvas); }
.table-danger,  .table-danger > th,  .table-danger > td   { background-color: var(--hk-bg-cream); }
.table-primary th, .table-primary td,
.table-success th, .table-success td,
.table-warning th, .table-warning td,
.table-danger  th, .table-danger  td,
.table-info th,    .table-info td { color: var(--hk-text); }

.list-group-item.active {
  background-color: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
  color: var(--hk-on-brand);                  /* 7.68:1 — AAA */
}
.list-group-item-primary { background-color: var(--hk-brand-soft); color: var(--hk-brand-text); }

.dropdown-item.active, .dropdown-item:active {
  background-color: var(--hk-brand-strong);
  color: var(--hk-on-brand);
}

.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
  background-color: var(--hk-brand-strong);
  color: var(--hk-on-brand);
}

.page-link       { color: var(--hk-text); background-color: var(--hk-bg-card); border-color: var(--hk-line-2); }
.page-link:hover { color: var(--hk-text); background-color: var(--hk-canvas); border-color: var(--hk-line-strong); }
.page-item.active .page-link {
  background-color: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
  color: var(--hk-on-brand);
}
.page-item.disabled .page-link { color: var(--hk-text-mute); background-color: var(--hk-canvas); }

.progress { background-color: var(--hk-bg-cream); }
.progress-bar            { background-color: var(--hk-brand-strong); }
.progress-bar.bg-warning { background-color: var(--hk-warn-strong); }
.progress-bar.bg-danger  { background-color: var(--hk-danger-strong); }

.custom-control-input:checked ~ .custom-control-label::before,
.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {
  background-color: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
}
.custom-range::-webkit-slider-thumb { background-color: var(--hk-brand-strong); }
.custom-range::-moz-range-thumb     { background-color: var(--hk-brand-strong); }
.custom-range::-ms-thumb            { background-color: var(--hk-brand-strong); }

/* Utilities. These keep !important because Bootstrap ships them that way and
   WHMCS templates rely on them beating a component's own colour. */
.bg-primary     { background-color: var(--hk-brand-strong) !important; }
.bg-success     { background-color: var(--hk-brand-strong) !important; }
.bg-info        { background-color: var(--hk-text-2) !important; }
.bg-warning     { background-color: var(--hk-warn-strong) !important; }
.bg-danger      { background-color: var(--hk-danger-strong) !important; }
.bg-dark        { background-color: var(--hk-ink) !important; }
.bg-light       { background-color: var(--hk-canvas) !important; }
.border-primary { border-color: var(--hk-brand) !important; }
.text-primary   { color: var(--hk-brand-text) !important; }   /* 10.75:1 — AAA */
.text-success   { color: var(--hk-brand-text) !important; }   /* 10.75:1 — AAA */
.text-info      { color: var(--hk-text-2) !important; }       /* 12.32:1 — AAA */
.text-warning   { color: var(--hk-warn-text) !important; }    /*  8.52:1 — AAA */
.text-danger    { color: var(--hk-danger-text) !important; }  /*  8.89:1 — AAA */
.text-muted     { color: var(--hk-text-mute) !important; }    /*  8.53:1 — AAA */
.text-dark      { color: var(--hk-text) !important; }

/* Tile stripes on the client home. Stock hands each tile its own crayon; here
   they are all the brand, which turns four competing stripes into one.
   The exact class names were read out of theme.css — note sun-flower,
   wet-asphalt and midnight-blue, which are easy to mistype as sun, wet and
   midnight and would then silently do nothing. */
.bg-color-blue, .bg-color-green, .bg-color-teal, .bg-color-emerald,
.bg-color-turquoise, .bg-color-lime { background-color: var(--hk-brand) !important; }
.bg-color-gold, .bg-color-sun-flower, .bg-color-orange { background-color: var(--hk-warn) !important; }
.bg-color-red, .bg-color-pomegranate { background-color: var(--hk-danger) !important; }
.bg-color-purple, .bg-color-magenta, .bg-color-pink, .bg-color-amethyst,
.bg-color-silver, .bg-color-asbestos, .bg-color-wet-asphalt,
.bg-color-midnight-blue { background-color: var(--hk-line-strong) !important; }


/* 4d. FOCUS AND CONTROL BOUNDARIES
   Bootstrap's focus affordance is a 0.2rem blue glow restated thirty-odd
   times with a per-component rgba. It is the wrong colour, it is under 3:1 on
   several surfaces, and on a solid emerald button it is invisible. Every rule
   that sets a glow is neutralised first, then one ring is applied.

   THE RING IS TWO-TONE, AND THAT IS NOT DECORATION.
   A single dark ring measures 19.06:1 against white but only 2.48:1 against
   --hk-brand-strong, so on a primary button — the single most important
   control on the page — a plain dark ring would FAIL 1.4.11. The inner halo
   in the contrasting tone means the ring always has a >=7:1 edge against
   whatever it sits on:

     light surfaces  outline #0b1018 (19.06:1 vs white page)
                     inner halo #ffffff (7.68:1 vs the emerald button beneath)
     dark surfaces   outline #ffffff (19.06:1 vs ink)
                     inner halo #0b1018

   outline-offset keeps the ring off the control's own border so the two never
   read as one thick edge. */
.btn:focus, .btn.focus,
.btn:not(:disabled):not(.disabled):active:focus,
.btn:not(:disabled):not(.disabled).active:focus,
.form-control:focus, .custom-select:focus,
.custom-control-input:focus ~ .custom-control-label::before,
.custom-file-input:focus ~ .custom-file-label,
.page-link:focus, a.badge:focus, .badge:focus,
.show > .btn.dropdown-toggle:focus {
  box-shadow: none;
}

/* :where() is kept in a rule of its own for the same reason as :has() above —
   an unparseable selector anywhere in a list drops the entire rule. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--hk-focus-width) solid var(--hk-focus);
  outline-offset: var(--hk-focus-offset);
  box-shadow: 0 0 0 var(--hk-focus-offset) var(--hk-on-brand);
}
.btn:focus-visible,
.form-control:focus-visible,
.custom-select:focus-visible,
.page-link:focus-visible,
.list-group-item:focus-visible,
.nav-link:focus-visible,
.dropdown-item:focus-visible,
.close:focus-visible {
  outline: var(--hk-focus-width) solid var(--hk-focus);
  outline-offset: var(--hk-focus-offset);
  box-shadow: 0 0 0 var(--hk-focus-offset) var(--hk-on-brand);
}
/* On the ink topbar and footer the polarity flips: white ring, ink halo. */
header.header .topbar :focus-visible,
footer.footer :focus-visible {
  outline-color: var(--hk-focus-on-dark);
  box-shadow: 0 0 0 var(--hk-focus-offset) var(--hk-ink);
}
/* The skip link is focused ON the page ground, where the standard ring is
   already correct, but it sits on emerald itself — same flip. */
.hk-skip-link:focus,
.hk-skip-link:focus-visible {
  outline: var(--hk-focus-width) solid var(--hk-focus);
  outline-offset: var(--hk-focus-offset);
  box-shadow: 0 0 0 var(--hk-focus-offset) var(--hk-on-brand);
}

/* Field outlines: the border IS the control, so 1.4.11 applies to it and 3:1
   is a hard floor. Stock Bootstrap ships #ced4da on .form-control, which
   measures 1.49:1 against white — a real 1.4.11 failure in the vendor theme,
   not a Hostika preference. */
.form-control, .custom-select, .custom-file-label {
  border-color: var(--hk-line-strong);        /* 3.82:1 white / 3.56:1 canvas / 3.29:1 cream */
  color: var(--hk-text);
  background-color: var(--hk-bg-card);
}
.form-control:focus, .custom-select:focus {
  border-color: var(--hk-text);               /* 19.06:1 */
}
.form-control::placeholder {
  color: var(--hk-text-mute);                 /* 8.53:1 — AAA, so a placeholder
                                                 is readable rather than a hint
                                                 you have to guess at */
  opacity: 1;
}
.form-control:disabled, .form-control[readonly] {
  background-color: var(--hk-canvas);
  color: var(--hk-text-2);
}
.form-control.is-invalid, .was-validated .form-control:invalid { border-color: var(--hk-danger); }
.form-control.is-valid,   .was-validated .form-control:valid   { border-color: var(--hk-brand); }
.invalid-feedback { color: var(--hk-danger-text); }   /* 8.89:1 — AAA */
.valid-feedback   { color: var(--hk-brand-text); }    /* 10.75:1 — AAA */

/* Unchecked checkbox and radio boxes are controls too, and an unchecked box
   is defined entirely by its outline. Stock leaves them at Bootstrap's
   #adb5bd, which is 2.07:1 on white — the empty state of every consent and
   terms checkbox in the order flow is currently below the 1.4.11 floor. */
.custom-control-label::before {
  border: 1px solid var(--hk-line-strong);
  background-color: var(--hk-bg-card);
}

/* Labels are read at body size, so they take the AAA ink tier, not a grey. */
label, .control-label, .col-form-label { color: var(--hk-text); }
.form-text, .help-block { color: var(--hk-text-mute); }   /* 8.53:1 — AAA */


/* 4e. TOUCH TARGETS
   48px minimum on everything interactive, matching the marketing site's
   --tap. Bootstrap's .btn is 38px tall, .btn-sm is 31px and nexus's .btn-xs
   is 24px. min-height plus inline-flex centring rather than extra padding, so
   nothing reflows and no table row grows a scrollbar. */
.btn, .nav-link, .page-link, .list-group-item-action,
.dropdown-item, .custom-select, .form-control,
.input-group-text, .close {
  min-height: var(--hk-tap);
  display: inline-flex;
  align-items: center;
}
.btn { justify-content: center; }

/* .btn-block is declared EARLIER in theme.css, so the .btn rule above would
   otherwise win on source order and silently un-stretch every full-width
   button — clientareahome.tpl alone has several. */
.btn-block { display: flex; width: 100%; }

/* inline-flex would break these two: a block-level field must stay block, and
   a textarea's rows must still govern its height. */
.form-control, .custom-select { display: block; }
textarea.form-control { min-height: calc(var(--hk-tap) * 2); }
.list-group-item-action, .dropdown-item { display: flex; }

/* Small buttons keep their small type but not their small hit area: the label
   shrinks, the target does not. */
.btn-sm, .btn-xs, .btn-group-sm > .btn, .btn-group-xs > .btn {
  min-height: var(--hk-tap);
  padding-top: 0;
  padding-bottom: 0;
}
/* Icon-only controls in dense table rows need width as well as height. */
.btn-xs, .btn-sm.btn-icon, .table .btn-sm { min-width: var(--hk-tap); }

/* A button group of 48px buttons is 48px tall; the group itself must not
   collapse it. */
.btn-group > .btn, .btn-group-vertical > .btn { min-height: var(--hk-tap); }

/* Checkbox and radio hit areas. The visible box stays 1rem; the LABEL becomes
   the target, which is what a customer actually aims at. */
.custom-control { min-height: var(--hk-tap); display: flex; align-items: center; }
.custom-control-label { display: inline-flex; align-items: center; min-height: var(--hk-tap); }

/* Pagination and tabs on a phone: stock renders 31px targets in a row. */
.page-item .page-link { min-width: var(--hk-tap); justify-content: center; }
.nav-tabs .nav-link, .nav-pills .nav-link { min-height: var(--hk-tap); }


/* ---------------------------------------------------------------------------
   5. THE CALM LAYER

   Everything here is a tone decision rather than a fix: quieter surfaces,
   fewer competing edges, no decoration that does not carry information.
   --------------------------------------------------------------------------- */

/* Cards: hairline border, NO shadow — the marketing site's rule, applied
   here. Stock nexus gives .card-header an rgba(0,0,0,.03) fill and a 1px
   rule, which on a page of eight cards reads as eight grey stripes. */
.card, .panel {
  background-color: var(--hk-bg-card);
  border: 1px solid var(--hk-line);
  box-shadow: none;
}
.card-header, .panel-heading {
  background-color: transparent;
  border-bottom: 1px solid var(--hk-line);
  color: var(--hk-text);
  font-weight: var(--hk-fw-semibold);
}
.card-footer, .panel-footer {
  background-color: transparent;
  border-top: 1px solid var(--hk-line);
}
/* clientareahome.tpl renders a .card-footer unconditionally for every panel,
   leaving a stray rule and 40px of dead space under panels that have none. */
.card-footer:empty { display: none; border-top: 0; padding: 0; }

/* The coloured 3px top border on home panels. Kept — it is the only thing
   distinguishing one card from the next at a glance — but reduced from
   fourteen meanings to three: brand for anything actionable, amber for
   attention, neutral for everything else.

   .card-accent-brand-cpanel-orange and .card-accent-brand-xovinow-blue are
   deliberately NOT in these lists. Those two identify third-party products by
   the vendor's own colour; repainting them emerald would misidentify the
   product rather than brand it. */
.card-accent-blue, .card-accent-teal, .card-accent-turquoise,
.card-accent-emerald, .card-accent-lime, .card-accent-green {
  border-top: 3px solid var(--hk-brand);
}
.card-accent-gold, .card-accent-sun-flower, .card-accent-orange {
  border-top: 3px solid var(--hk-warn);
}
.card-accent-red, .card-accent-pomegranate {
  border-top: 3px solid var(--hk-danger);
}
.card-accent-purple, .card-accent-pink, .card-accent-magenta,
.card-accent-amethyst, .card-accent-silver, .card-accent-asbestos,
.card-accent-wet-asphalt, .card-accent-midnight-blue {
  border-top: 3px solid var(--hk-line-2);
}

/* Page ground and chrome. html/body is ink so the footer bleeds to the bottom
   of short pages; section#main-body is the canvas the cards sit on. */
html, body { background-color: var(--hk-ink); }
section#main-body { background-color: var(--hk-canvas); }

/* SKIP LINK (markup added in header.tpl).
   Styled to match assets/style.css .skip-link on the marketing site: hidden
   off-screen, slides in on focus, 48px tall, emerald with white at 7.68:1. */
.hk-skip-link {
  position: absolute;
  top: -80px;
  left: var(--hk-sp-8);
  z-index: 1080;                              /* above Bootstrap's modal-backdrop */
  display: inline-flex;
  align-items: center;
  min-height: var(--hk-tap);
  padding: 0 var(--hk-sp-16);
  background: var(--hk-brand-strong);
  color: var(--hk-on-brand);                  /* 7.68:1 — AAA */
  border-radius: var(--hk-radius);
  font-weight: var(--hk-fw-semibold);
  font-size: var(--hk-fs-base);
  text-decoration: none;
}
.hk-skip-link:focus { top: var(--hk-sp-8); color: var(--hk-on-brand); }

/* The top strip. Stock paints it --grayscale-accented (#374151) with
   rgba(255,255,255,0.65) text, which composites to #b9bdc2 and measures
   5.46:1 — AA, not AAA, and it carries the "logged in as" line and the
   notifications count. Ink ground plus the on-dark text tier takes it to
   12.84:1 and matches the marketing site's dark surfaces exactly. */
header.header .topbar {
  background-color: var(--hk-ink);
  color: var(--hk-on-dark-2);                 /* 12.84:1 composited — AAA */
}
header.header .topbar .btn,
header.header .topbar .active-client .btn,
header.header .topbar .active-client .input-group-text {
  color: var(--hk-on-dark-2);
  background-color: transparent;
  border-color: transparent;
}
header.header .topbar .btn:hover { color: var(--hk-on-dark); }
header.header .topbar .active-client .btn.btn-active-client span {
  border-bottom: 1px dashed var(--hk-on-dark-line-strong);   /* 3.56:1 */
}

header.header {
  background-color: var(--hk-bg-card);
  border-bottom: 1px solid var(--hk-line);
}
header.header .navbar a { color: var(--hk-text); }
header.header .toolbar .nav-link {
  border: 1px solid var(--hk-line-strong);    /* 3.82:1 — it is a control */
  color: var(--hk-text-2);
}
header.header .toolbar .nav-link:hover { color: var(--hk-text); background-color: var(--hk-canvas); }
header.header .search { border-color: var(--hk-line-strong); }
header.header .search .btn { color: var(--hk-text-2); }
header.header .search:focus-within { border-color: var(--hk-text); }

/* Main navigation, matching the marketing site's flat top nav: no fills, an
   emerald underline on the current page, ink text throughout. */
.main-navbar-wrapper { background-color: var(--hk-bg-card); border-bottom: 1px solid var(--hk-line); }
.main-navbar-wrapper .navbar-nav .nav-link {
  color: var(--hk-text-2);                    /* 12.32:1 — AAA */
  font-weight: var(--hk-fw-medium);
  border-bottom: 2px solid transparent;
}
.main-navbar-wrapper .navbar-nav .nav-link:hover { color: var(--hk-text); }
.main-navbar-wrapper .navbar-nav .nav-item.active > .nav-link,
.main-navbar-wrapper .navbar-nav .nav-link.active {
  color: var(--hk-brand-text);                /* 10.75:1 — AAA */
  border-bottom-color: var(--hk-brand);
  /* The underline is the redundant cue; colour alone never marks the current
     page (1.4.1). aria-current, where WHMCS emits it, is the third. */
}

footer.footer {
  background-color: var(--hk-ink);
  color: var(--hk-on-dark-2);                 /* 12.84:1 — AAA */
  border-top: 1px solid var(--hk-on-dark-line);
}
footer.footer a { color: var(--hk-on-dark-2); text-decoration: underline; }
footer.footer a:hover { color: var(--hk-on-dark); }
footer.footer .btn {
  color: var(--hk-on-dark);
  border-color: var(--hk-on-dark-line-strong);  /* 3.56:1 — meets 1.4.11 */
  background-color: transparent;
}
/* Footer small print — copyright line, currency and language switcher labels.
   Stock's footer body text is plain #fff on --bg-inverted (17.74:1, fine);
   what is NOT fine is anything in there wearing .text-muted, which stock
   resolves to #9ca3af and measures 6.99:1 on that ground — a hundredth short
   of AAA, which is the most annoying way to miss it. This is the one tier
   below body copy that is comfortably AAA on ink. */
footer.footer small,
footer.footer .small,
footer.footer .text-muted {
  color: var(--hk-on-dark-mute) !important;     /* -> #a2a4a7, 7.63:1 — AAA */
}

/* THE LOGO.
   header.tpl renders {$assetLogoPath} — the file the owner uploads in WHMCS
   admin — and falls back to the company name as text. Both branches are
   sized here so the header geometry is identical either way and the navbar
   does not jump when the image lands.

   KNOWN ISSUE, NOT FIXABLE FROM THIS THEME: the configured logo today is
   client/assets/img/logo.png at 1448x1086 and 813,328 bytes, displayed by
   stock nexus at roughly 80x60 via `max-width:400px; max-height:60px`. Every
   page in the client area therefore ships 813 KB for a thumbnail. The file
   lives outside templates/ and is referenced by filename in
   whmcs-pdf/invoicepdf.tpl and quotepdf.tpl, so replacing it is the image
   owner's change, not this theme's. Constraining it here fixes the layout,
   not the download. */
header.header .navbar-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--hk-sp-8);
  min-height: var(--hk-tap);
  padding: var(--hk-sp-4) 0;
  text-decoration: none;
}
header.header .logo-img {
  width: auto;
  height: 40px;
  max-width: 240px;
  max-height: 40px;
  display: block;
}
/* The no-logo fallback: the real company name, set as a wordmark. No invented
   monogram and no placeholder image — if there is no logo the page says the
   company's name in the brand's typeface, which is honest and is also what
   the marketing site's header does. */
.hk-brand-word {
  font-weight: var(--hk-fw-bold);
  font-size: var(--hk-fs-lg);
  letter-spacing: var(--hk-ls-snug);
  color: var(--hk-text);                      /* 19.06:1 — AAA */
  white-space: nowrap;
}

/* Breadcrumbs: stock is a filled #e9ecef bar. A row of small text with a
   hairline under it says the same thing in a third of the space. */
.master-breadcrumb { background-color: var(--hk-bg-card); }
.breadcrumb {
  background-color: transparent;
  border-bottom: 1px solid var(--hk-line);
  border-radius: 0;
  padding-left: 0;
  padding-right: 0;
  margin-bottom: 0;
  font-size: var(--hk-fs-sm);
}
.breadcrumb-item, .breadcrumb-item a { color: var(--hk-text-mute); }   /* 8.53:1 */
.breadcrumb-item.active { color: var(--hk-text); }

/* Tables: horizontal rules only, no vertical grid, no zebra. Billing tables
   are read one row at a time, and a zebra stripe puts half the rows on a
   surface the text was never rated against. */
.table { color: var(--hk-text); }
.table th, .table td { border-top: 1px solid var(--hk-line); }
.table thead th {
  border-bottom: 1px solid var(--hk-line-2);
  color: var(--hk-text-mute);                 /* 8.53:1 — AAA */
  font-size: var(--hk-fs-sm);
  font-weight: var(--hk-fw-semibold);
  letter-spacing: var(--hk-ls-caps);
  text-transform: uppercase;
}
.table-striped tbody tr:nth-of-type(odd) { background-color: transparent; }
.table-hover tbody tr:hover { background-color: var(--hk-canvas); color: var(--hk-text); }
.table-bordered, .table-bordered th, .table-bordered td { border-color: var(--hk-line); }

/* Sidebar. Stock marks the active item with a tinted fill only: --bg-lifted
   (#f4f5f7) against the white card, which is a 1.09:1 difference — invisible
   on a dimmed laptop screen and completely absent in high-contrast mode. An
   emerald leading rule plus a weight change plus the tint makes the current
   page findable three ways instead of none (1.4.1). */
.sidebar .card { border-color: var(--hk-line); }
.sidebar .list-group-item {
  color: var(--hk-text);
  border-left: 3px solid transparent;
}
.sidebar .list-group-item.active,
.sidebar .list-group-item.active:hover,
.sidebar .list-group-item.active:focus {
  background-color: var(--hk-brand-soft);
  border-left-color: var(--hk-brand);
  color: var(--hk-brand-text);                /* 10.20:1 on --hk-brand-soft — AAA */
  font-weight: var(--hk-fw-semibold);
}
.sidebar .list-group-item .badge {
  background-color: var(--hk-bg-cream);
  color: var(--hk-text-2);                    /* 10.61:1 on cream — AAA */
}

/* Modals and dropdowns sit above the page, so they are the one place a shadow
   still carries information (which layer am I on). */
.modal-content { border: 1px solid var(--hk-line); box-shadow: var(--hk-shadow-lg); }
.modal-header, .modal-footer { border-color: var(--hk-line); }
.dropdown-menu { border: 1px solid var(--hk-line); box-shadow: var(--hk-shadow-md); }
.popover { border-color: var(--hk-line); }
.popover-user-notifications { border-color: var(--hk-line); }
.tooltip-inner { background-color: var(--hk-ink); color: var(--hk-on-dark); }   /* 19.06:1 */

/* Motion. The marketing site's motion.css is deliberately not imported here —
   the client area gets no entrance animations at all, which is the calm
   answer. What is left is state transition on the marketing site's easing. */
.btn, .form-control, .custom-select, .list-group-item, .page-link, .card,
.nav-link, .dropdown-item {
  transition: background-color .18s var(--hk-t),
              border-color .18s var(--hk-t),
              color .18s var(--hk-t);
}
@media (prefers-reduced-motion: reduce) {
  /* Matches the guard already in assets/style.css. Scoped to * because WHMCS
     ships jQuery animations and Bootstrap collapse/fade, and enumerating
     those would rot on the first upgrade. */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Print. Invoices get printed. Ink backgrounds do not. */
@media print {
  html, body, section#main-body { background: #fff !important; color: #000 !important; }
  header.header, footer.footer, .sidebar, .master-breadcrumb, .hk-skip-link { display: none !important; }
  .card { border: 1px solid #999 !important; }
}


/* ---------------------------------------------------------------------------
   6. HOOK PANELS

   Styles for the markup emitted by
   client/includes/hooks/hostika_dashboard.php. Everything is namespaced .hk-
   so that a WHMCS upgrade renaming a stock class cannot silently restyle
   these, and so `grep -r hk-` finds both halves of the feature at once.

   The hook renders inside a stock .card via bodyHtml, so these rules only
   have to describe the interior.
   --------------------------------------------------------------------------- */

/* --- Onboarding checklist --- */
.hk-steps { list-style: none; margin: 0; padding: 0; }
.hk-step {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: var(--hk-sp-12);
  align-items: start;
  padding: var(--hk-sp-12) 0;
  border-bottom: 1px solid var(--hk-line);
}
.hk-step:last-child { border-bottom: 0; }
.hk-step-mark {
  width: 28px;
  height: 28px;
  border-radius: var(--hk-radius-pill);
  border: 2px solid var(--hk-line-strong);    /* 3.82:1 — this shape carries state */
  display: grid;
  place-items: center;
  font-size: var(--hk-fs-sm);
  font-weight: var(--hk-fw-bold);
  color: var(--hk-text-mute);
  background: var(--hk-bg-card);
}
.hk-step-title {
  font-weight: var(--hk-fw-semibold);
  color: var(--hk-text);
  line-height: var(--hk-lh-normal);
}
.hk-step-note {
  color: var(--hk-text-mute);                 /* 8.53:1 — AAA */
  font-size: var(--hk-fs-sm);
  line-height: var(--hk-lh-normal);
  margin-top: 2px;
}
/* Done: emerald mark, ink text. Deliberately no strike-through — a completed
   step is still information the customer may want to re-read. The tick glyph
   inside the mark is what says "done"; the fill is the second cue. */
.hk-step.is-done .hk-step-mark {
  background: var(--hk-brand-strong);
  border-color: var(--hk-brand-strong);
  color: var(--hk-on-brand);                  /* 7.68:1 — AAA */
}
/* Current: the only emphasised row on the panel. */
.hk-step.is-current .hk-step-mark {
  border-color: var(--hk-brand);
  color: var(--hk-brand-text);                /* 10.20:1 on --hk-brand-soft — AAA */
  background: var(--hk-brand-soft);
}
.hk-step.is-current .hk-step-title { color: var(--hk-brand-text); }
.hk-step.is-todo .hk-step-title { color: var(--hk-text-2); font-weight: var(--hk-fw-medium); }

/* --- Welcome panel --- */
.hk-welcome {
  display: flex;
  gap: var(--hk-sp-16);
  align-items: flex-start;
  flex-wrap: wrap;
}
.hk-welcome-portrait {
  width: 72px;
  height: 72px;
  border-radius: var(--hk-radius-pill);
  object-fit: cover;
  border: 1px solid var(--hk-line);
  flex: none;
  background: var(--hk-canvas);
}
/* Placeholder portrait: an obviously-empty dashed slot on the canvas grey, so
   the panel has correct geometry before a real photograph exists.
   Deliberately NOT a stock avatar illustration — an empty slot is easy to
   notice in review; a plausible wrong face is not. */
.hk-welcome-portrait--placeholder {
  display: grid;
  place-items: center;
  color: var(--hk-text-mute);                 /* 8.53:1 — AAA */
  font-size: var(--hk-fs-sm);
  letter-spacing: var(--hk-ls-caps);
  text-transform: uppercase;
  border: 1px dashed var(--hk-line-strong);
}
.hk-welcome-body { flex: 1 1 260px; min-width: 0; }
.hk-welcome-name {
  font-weight: var(--hk-fw-bold);
  color: var(--hk-text);
  font-size: var(--hk-fs-lg);
  letter-spacing: var(--hk-ls-snug);
}
.hk-welcome-role {
  color: var(--hk-text-mute);
  font-size: var(--hk-fs-sm);
  margin-bottom: var(--hk-sp-8);
}
.hk-welcome-text { color: var(--hk-text-2); line-height: var(--hk-lh-body); }
.hk-welcome-contact {
  display: flex;
  flex-wrap: wrap;
  gap: var(--hk-sp-8);
  margin-top: var(--hk-sp-16);
}

/* THE "NOT REAL YET" TREATMENT.
   Amber hairline, uppercase micro-label, readable amber text. Loud enough to
   be caught in a screenshot review, quiet enough not to break the page if it
   ships by accident for a day. Anything the brief says must render as
   obviously-empty rather than as invented content — a founder's name, a phone
   number, a portrait, a testimonial — wears this. */
.hk-placeholder {
  border: 1px dashed var(--hk-warn);          /* 5.02:1 — well past 3:1 */
  background: var(--hk-accent-soft);
  color: var(--hk-warn-text);                 /* 7.74:1 on --hk-accent-soft — AAA */
  border-radius: var(--hk-radius);
  padding: var(--hk-sp-8) var(--hk-sp-12);
  font-size: var(--hk-fs-sm);
  line-height: var(--hk-lh-normal);
}
.hk-placeholder::before {
  content: "PLACEHOLDER";
  display: block;
  font-size: var(--hk-fs-meta);
  font-weight: var(--hk-fw-bold);
  letter-spacing: var(--hk-ls-caps);
  margin-bottom: 2px;
}

/* --- Allowance meter --- */
.hk-allowance { display: grid; gap: var(--hk-sp-8); }
.hk-allowance-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--hk-sp-12);
}
.hk-allowance-figure {
  font-size: var(--hk-fs-2xl);
  font-weight: var(--hk-fw-bold);
  letter-spacing: var(--hk-ls-tight);
  line-height: 1;
  color: var(--hk-text);
}
.hk-allowance-of { color: var(--hk-text-mute); font-size: var(--hk-fs-sm); }
.hk-meter {
  height: 8px;
  border-radius: var(--hk-radius-pill);
  background: var(--hk-bg-cream);
  overflow: hidden;
}
.hk-meter-fill {
  height: 100%;
  background: var(--hk-brand);
  border-radius: inherit;
}
.hk-meter-fill.is-low   { background: var(--hk-warn); }
.hk-meter-fill.is-spent { background: var(--hk-danger); }
/* The meter is decoration. The figure above it carries the number and the
   hook emits the same value as text, so colour is never the only cue (1.4.1)
   and the bar never has to meet a text ratio. */
.hk-allowance-note { color: var(--hk-text-mute); font-size: var(--hk-fs-sm); }

/* --- Shortcut row --- */
.hk-actions { display: flex; flex-wrap: wrap; gap: var(--hk-sp-8); }
.hk-actions .btn { flex: 1 1 auto; }

/* --- Small print used across the hook panels --- */
.hk-meta {
  color: var(--hk-text-mute);                 /* 8.53:1 — AAA */
  font-size: var(--hk-fs-sm);
  line-height: var(--hk-lh-normal);
}
