/* ============================================================================
   Hostika — WHMCS ORDER FORM BRAND LAYER
   client/templates/orderforms/hostika_cart/css/custom.css
   ----------------------------------------------------------------------------
   WHAT THIS FILE IS

   The second of the two files in this order form. theme.yaml declares
   `parent: nexus_cart`; this file is everything else. There is no template
   here and there does not need to be — see "WHAT CANNOT BE DONE" at the foot
   of this file.

   HOW IT GETS LOADED

   templates/orderforms/standard_cart/common.tpl, which every page of this
   cart includes, ends with:

       {assetExists file="custom.css"}
       <link rel="stylesheet" href="{$__assetPath__}?v={$versionHash}" />
       {/assetExists}

   `assetExists` searches the active order form first and walks up the parent
   chain, so with hostika_cart active it finds THIS file rather than
   nexus_cart's. The <link> is emitted in the body, after the main theme's
   <head>, which is what lets the token block below win a same-specificity tie
   against templates/hostika/css/custom.css without needing !important.

   HOW IT REACHES THE SHADOW DOM — THE WHOLE MECHANISM IN ONE PLACE

   nexus_cart's product browser and domain search are a Vue SPA in a closed-
   over shadow tree. js/main.min.js does, in effect:

       root = el.attachShadow({mode: "open"})
       style.textContent = vuelessRuntimeCss + "\n" + style.min.css
                                             + "\n" + custom.css
       root.insertBefore(style, root.firstChild)

   Both stylesheet URLs are built with `new URL("../css/<name>", <script src>)`
   — resolved against the SCRIPT's own address, NOT through WHMCS asset
   resolution. main.min.js comes from nexus_cart (this theme ships no js/), so
   the SPA always fetches nexus_cart/css/custom.css into the shadow root.

   THIS FILE NEVER ENTERS THE SHADOW TREE. That is not a limitation, it is the
   extension point. nexus_cart/css/custom.css is a pure indirection table:

       :host, :root {
           --vl-primary: var(--primary);
           --vl-bg:      var(--bg);
           ... 53 of these ...
       }

   Those `var(--primary)` lookups are resolved against #nexus-root, the host
   element, which sits in the light DOM and inherits from :root. So defining
   `--primary` on :root out here sets `--vl-primary` in there, which
   style.min.css maps to `--color-primary`, which its Tailwind utilities
   paint with. One declaration, three hops, no JavaScript.

   That indirection table is the complete list of what pierces the boundary.
   Section 1 below defines every name in it. Nothing else is reachable from
   :root, because a declaration that matches the host element directly always
   beats a value inherited into it — see section 3.

   MEASURED, NOT REMEMBERED

   Every number below was counted in this tree:

     var() references in nexus_cart/css/style.min.css ........ 1587
     of which var(--color-<name>) colour references .......... 583
       resolving through the 53 tokens in section 1 .......... 523   (89.7%)
       resolving to Tailwind's raw palette, unreachable ....... 60   (10.3%)
     var(--vl-*) references in style.min.css ................. 158
     names nexus_cart/css/custom.css dereferences ............ 53
     var() references in standard_cart/css/all.css ............ 0
     hardcoded colour literals in standard_cart/css/all.css .. 46 KB worth
     order form templates nexus_cart overrides ................ 2
     order form templates inherited from standard_cart ....... 28

   WORKS UNDER EITHER MAIN THEME, AND EITHER PARENT

   Two independent settings can move under this file, so it is written not to
   care about either:

   1. Template = six (today) or hostika (after deploy). Colours are written
      `var(--hk-brand, #047857)`. templates/hostika/css/custom.css defines the
      --hk-* family; six does not. Under hostika the cart tracks the client
      area exactly, including a swap from the cool palette to the warm one.
      Under six the literal fallback keeps the cart on brand anyway. Without
      this file and under six, `--primary` is undefined, `--vl-primary`
      becomes the guaranteed-invalid value and the SPA's primary colour
      resolves to `unset` — a cart with no buttons you can see.

   2. parent = nexus_cart or standard_cart. Section 1 brands the SPA; section
      4 brands the classic light-DOM markup. Under nexus_cart the classic
      markup is still every page after "add to cart", so section 4 is never
      wasted; under standard_cart it is the whole cart. See theme.yaml for
      when you would change the parent and why.

   DEFERENCE TO THE MAIN THEME

   templates/hostika/css/custom.css carries 16 rules of its own scoped
   `body #order-standard_cart ...`. Everything in section 4 here is scoped
   `#order-standard_cart ...` with no `body` prefix — one element lower in
   specificity — so where the two files touch the same declaration the main
   theme wins and this file is the floor under it. That is deliberate: when
   Template = hostika, the client area's own stylesheet should be the one
   deciding what the cart looks like.

   TONE

   Same as the client area: calmer than hostika-bg.com. This is a checkout,
   which is a chore, and the only thing on the page that should be loud is the
   button that finishes it. Emerald appears on primary actions and success
   only. "Info" and "notice" are graphite, not blue and purple.

   CONTRAST

   AAA (7:1) for anything at body size, 3:1 for large text and for non-text UI
   boundaries. Ratios quoted below are against the surface the colour actually
   lands on and were computed with the WCAG 2.1 sRGB formula.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   1. THE 53 TOKENS THAT PIERCE THE SHADOW BOUNDARY

   Same names, same order, same grouping as
   templates/orderforms/nexus_cart/css/custom.css, so that diffing the two
   files after a WHMCS upgrade shows exactly which tokens WHMCS added or
   dropped from the indirection table.

   The mapping onto --hk-* is identical to section 3 of
   templates/hostika/css/custom.css. It is repeated rather than referenced
   because that file is a different theme and may not be loaded — but any
   change there must be made here too, or the cart and the client area will
   drift apart at exactly the moment a customer is comparing them.

   All 53 are declared even where the value is unchanged from stock: this file
   REPLACES nexus_cart/css/custom.css as the light-DOM stylesheet, and an
   undefined custom property resolves to `unset`, not to a sane default. A
   name dropped from this list paints nothing at all.
   --------------------------------------------------------------------------- */

:root {

  /* Primary colors
     --hk-brand-strong (#065f46), not --hk-brand (#047857): white on #065f46
     is 7.68:1 (AAA), white on #047857 is 5.48:1 (AA only). "Continue" and
     "Complete order" are the two controls in this whole product that must
     clear AAA. */
  --primary:          var(--hk-brand-strong, #065f46);
  --primary-lifted:   var(--hk-brand,        #047857);
  --primary-accented: var(--hk-brand-2,      #065f46);

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

  /* Success colors
     One green in the whole funnel. Stock nexus ships #00a63e, a different
     green from the brand emerald — near-miss greens sitting next to each
     other in a checkout are what makes a cart feel bolted on. */
  --success:          var(--hk-brand,      #047857);
  --success-lifted:   var(--hk-brand-2,    #065f46);
  --success-accented: var(--hk-brand-text, #044733);

  /* Info colors
     Deliberately NOT blue. Stock is #155dfc, and 38 utility references would
     walk royal blue back into a brand that removed it on purpose — the domain
     TLD chrome and every informational badge in the SPA. Informational states
     read as graphite; the icon and the words carry the meaning. */
  --info:          var(--hk-text-2, #2f3540);
  --info-lifted:   var(--hk-text,   #0b1018);
  --info-accented: var(--hk-text,   #0b1018);

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

  /* Warning colors — amber stays amber; this is the only warm hue in the cool
     palette and it is carrying meaning, not decoration. */
  --warning:          var(--hk-warn,        #b45309);
  --warning-lifted:   var(--hk-warn-strong, #7c3a06);
  --warning-accented: var(--hk-warn-text,   #7c3a06);

  /* Error colors
     A declined card and a failed domain check both land here, so the text
     forms matter: #941313 is 8.89:1 on white (AAA) and carries white at the
     same ratio when it is the fill. */
  --error:          var(--hk-danger,        #b91c1c);
  --error-lifted:   var(--hk-danger-strong, #941313);
  --error-accented: var(--hk-danger-text,   #941313);

  /* Grayscale colors — 38 base references, the SPA's default ink. */
  --grayscale:          var(--hk-text,      #0b1018);
  --grayscale-lifted:   var(--hk-text-2,    #2f3540);
  --grayscale-accented: var(--hk-text-mute, #464d58);

  /* Neutral colors */
  --neutral:          var(--hk-text-mute, #464d58);
  --neutral-lifted:   var(--hk-text-2,    #2f3540);
  --neutral-accented: var(--hk-text,      #0b1018);

  /* Text neutral colors
     --text-muted and --text-lifted collapse to the same value on purpose.
     Stock puts --text-muted on #9ca3af — 2.54:1 on white — and then uses it
     for real caption text: product descriptions, renewal periods, the "per
     year" under a domain price. Hostika has exactly one grey that clears 7:1
     at body size, so both tiers get it. Losing a tier of visual hierarchy in
     a checkout is much the cheaper trade. */
  --text-inverted: var(--hk-on-brand, #ffffff);
  --text-muted:    var(--hk-text-mute, #464d58);   /* 8.53:1 — AAA (stock 2.54:1) */
  --text-lifted:   var(--hk-text-mute, #464d58);
  --text-accented: var(--hk-text-2,    #2f3540);
  --text:          var(--hk-text,      #0b1018);   /* 19.06:1 — AAA */

  /* Border neutral colors
     --border-muted and --border are DECORATIVE tiers (1.26:1 and 1.58:1) and
     nexus_cart only uses them for card and panel edges. --border-lifted and
     --border-accented are what the SPA puts on control outlines, so both get
     --hk-line-strong, which is the lightest grey that still meets 1.4.11's
     3:1 on all three light surfaces (3.82 / 3.56 / 3.29). */
  --border-muted:    var(--hk-line,        #e2e5ea);
  --border:          var(--hk-line-2,      #c9ced6);
  --border-lifted:   var(--hk-line-strong, #7c838f);
  --border-accented: var(--hk-line-strong, #7c838f);

  /* Background neutral colors
     --bg is the card surface the SPA paints its product tiles on, --bg-lifted
     and --bg-muted the canvas behind them, --bg-inverted the one dark fill
     (9 references: the selected-plan strip and the cart badge). */
  --bg:          var(--hk-bg-card,   #ffffff);
  --bg-muted:    var(--hk-canvas,    #f6f7f9);
  --bg-lifted:   var(--hk-canvas,    #f6f7f9);
  --bg-accented: var(--hk-bg-cream,  #eceef2);
  --bg-inverted: var(--hk-ink,       #0b1018);

  /* Font sizes
     Stock's four steps are 10 / 12 / 14 / 16px; the first two are below the
     readable floor. Re-pointed at the Hostika scale.

     IMPORTANT: three of these four do NOT reach the SPA, and that is not a
     bug in this file. style.min.css declares --text-xs, --text-sm and
     --text-lg on :host as Tailwind's own type scale, and a declaration on the
     host beats a value inherited into it. Only --text-md is free. This is
     already true of stock nexus_cart — the indirection table asks for
     `var(--text-lg)` and gets Tailwind's 1.125rem, not nexus's 1rem.

     They are declared anyway, for the light DOM and for the day WHMCS
     renames the collision away. Overriding the three from #nexus-root would
     work (see section 3) and is deliberately NOT done: --text-lg means 16px
     to nexus and 18px to Tailwind, so forcing it would silently shrink every
     `text-lg` utility in a shadow tree that cannot be inspected. */
  --text-xs: var(--hk-fs-meta, .75rem);    /* 12px — metadata only, never body */
  --text-sm: var(--hk-fs-sm,   .875rem);   /* 14px, lifted to 16px below 600px */
  --text-md: var(--hk-fs-sm,   .875rem);
  --text-lg: var(--hk-fs-base, 1rem);      /* 16px — the body floor */

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

  /* Rounding
     The cool palette is the tight variant: 4px on controls, 8px on anything
     that frames. Pointing these three at the tokens is what makes a palette
     switch move the geometry as well as the colour — warm is 9px / 18px. */
  --rounding-sm: var(--hk-radius-sm, 4px);
  --rounding-md: var(--hk-radius,    4px);
  --rounding-lg: var(--hk-radius-lg, 8px);

  /* Other
     --disabled-opacity raised from stock's 25%. Disabled controls are exempt
     from 1.4.3, but the disabled control in THIS product is the checkout
     button on an empty cart, and at a quarter opacity the customer cannot
     read why they are stuck. 55 references in style.min.css — this is the
     single most-read token in the SPA. */
  --letter-spacing:   0em;
  --disabled-opacity: 45%;
}


/* ---------------------------------------------------------------------------
   2. MOBILE TYPE FLOOR

   16px minimum for anything a person reads on a phone, enforced on the token
   rather than per component — the same contract as assets/tokens-cool.css and
   the same 600px breakpoint, so type and geometry step together across the
   marketing site, the client area and the cart.

   --text-xs is deliberately not lifted: it is metadata only.

   Under Template = hostika this is redundant, because --hk-fs-sm is already
   lifted to --hk-fs-base by the main theme's own media block and these
   declarations resolve to the same 1rem. It exists for Template = six, where
   the literal .875rem fallback above would otherwise stay 14px on a phone.
   --------------------------------------------------------------------------- */

@media (max-width: 600px) {
  :root {
    --text-sm: var(--hk-fs-base, 1rem);
    --text-md: var(--hk-fs-base, 1rem);
  }
}


/* ---------------------------------------------------------------------------
   3. THE HOST-LEVEL LEVER

   Section 1 works by inheritance: :root sets a value on <html>, it inherits
   down to #nexus-root, and the shadow tree reads it off the host. Inheritance
   only supplies a value when nothing declares one, so any token that
   style.min.css declares in its own `:host { }` block is out of reach from
   :root. Grepped, that is exactly five names: --text-xs, --text-sm,
   --text-lg, --font-sans and --spacing.

   There is a way in. Per the cascade's encapsulation-context step, which is
   evaluated BEFORE specificity, a normal declaration from the outer tree beats
   a normal declaration from an inner tree when both match the same element. A
   light-DOM rule that matches #nexus-root directly therefore overrides
   style.min.css's `:host` rules regardless of how the two selectors score.
   (The reverse holds for !important, which is why none is used here.)

   Exactly one of the five is worth taking, and the other four are listed with
   the reason they are left alone:

     --font-sans   TAKEN. style.min.css pins the SPA to the vueless system
                   stack, so without this the browse step renders in Segoe UI
                   while the page around it renders in Inter — on the same
                   screen, a few pixels apart. @font-face is document-scoped
                   and does reach shadow trees, so under Template = hostika
                   the face registered by templates/hostika/css/custom.css is
                   available in here. Under six it is not, and the stack falls
                   through to system-ui exactly as before. Nothing to load,
                   nothing to break.

     --text-xs     LEFT. Identical value either way (.75rem).
     --text-sm     LEFT. Identical value either way (.875rem).
     --text-lg     LEFT. NOT identical — nexus means 16px, Tailwind means
                   18px — and taking it would rescale every `text-lg` utility
                   in the SPA. See the note in section 1.
     --spacing     LEFT. It is `var(--vl-spacing)`, vueless's base spacing
                   unit, and every padding and gap utility in the shadow tree
                   is a multiple of it. Changing the base unit of a Vue SPA
                   whose markup cannot be inspected or edited is a structural
                   change wearing a token's clothes.
   --------------------------------------------------------------------------- */

#nexus-root {
  --font-sans: var(--hk-font-sans,
               'InterVariable', 'Inter', system-ui, -apple-system, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif);
}


/* ---------------------------------------------------------------------------
   4. THE LIGHT DOM — CLASSIC standard_cart MARKUP

   Everything after "add to cart" is standard_cart's 2014 Bootstrap markup:
   checkout.tpl, configureproduct.tpl, configuredomains.tpl, addons.tpl,
   complete.tpl, fraudcheck.tpl, error.tpl and the sidebar partials. That is
   true under BOTH parents — nexus_cart replaces two templates out of thirty —
   so none of this is fallback-only unless a rule says so.

   standard_cart/css/all.css makes zero var() references, so there is no token
   to turn for any of it. Only four things are done here, all of them floors
   rather than styling: the main theme is what should be styling this surface
   when it is loaded, and every selector below is one element less specific
   than its counterpart there so that it always wins.
   --------------------------------------------------------------------------- */

/* 4a. TOUCH TARGETS — 48px, the project floor, on every control in the cart.
   Bootstrap's .btn lands at ~34px and .form-control at exactly 34px.

   The padding is grown rather than the display mode changed. Switching .btn
   to inline-flex would be the usual way to centre the label inside a taller
   box, and it would be a bug: checkout.tpl hides eleven controls with
   `.w-hidden { display: none }` at specificity (0,1,0) — the "already
   registered" / "new signup" pair, four `domain-contact-support` buttons and
   the please-wait spinners — and any `#order-standard_cart .btn` rule setting
   `display` scores (1,1,0) and would put every one of them back on screen.

   calc((48px - 1.5em) / 2) is "half of whatever is left after one line of
   text", so it centres correctly at all four Bootstrap sizes without
   enumerating them: 16px text -> 12px, .btn-sm 14px -> 13.5px, .btn-xs 12px
   -> 15px, .btn-lg 18px -> 10.5px. Horizontal padding is untouched. */
#order-standard_cart .btn {
  min-height:     var(--hk-tap, 48px);
  padding-top:    calc((var(--hk-tap, 48px) - 1.5em) / 2);
  padding-bottom: calc((var(--hk-tap, 48px) - 1.5em) / 2);
}

/* .form-control carries a fixed `height`, which min-height cannot beat.
   Released to auto first. Inputs and selects centre their own value
   vertically, so no padding change is needed; textarea keeps its rows. */
#order-standard_cart .form-control,
#order-standard_cart select.form-control {
  height:     auto;
  min-height: var(--hk-tap, 48px);
}

/* Input group parts, so an addon or an attached button does not end up
   shorter than the field it is glued to. .input-group-addon is a table-cell
   in Bootstrap 3 and ignores min-height, but the row is sized by its tallest
   cell — which is now the field — so it matches anyway. */
#order-standard_cart .input-group-addon,
#order-standard_cart .input-group-btn > .btn {
  min-height: var(--hk-tap, 48px);
}

/* 4b. FOCUS VISIBILITY
   :focus-visible only, so a mouse click does not leave a ring behind. The
   colour is ink rather than emerald by decision — emerald is 3.4:1 against
   some of these surfaces and vanishes entirely on --hk-brand-soft, and a
   focus ring that disappears on one panel is worse than no system at all. */
#order-standard_cart :is(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline:        var(--hk-focus-width, 3px) solid var(--hk-focus, #0b1018);
  outline-offset: var(--hk-focus-offset, 2px);
}

/* 4c. THE NAVY CART CHROME
   standard_cart hardcodes #058 — a 1990s navy, 8.59:1 on white but not a
   Hostika colour and not close to one — as the view-cart header fill and the
   2px rule under the item list.

   These two selectors are reached only when the parent is standard_cart:
   .view-cart-items and .btn-remove-from-cart appear in exactly one template,
   standard_cart/viewcart.tpl, which nexus_cart replaces with the SPA. They
   are here so that changing one word in theme.yaml gives a branded classic
   cart rather than a navy one. Under nexus_cart they cost four unmatched
   selectors. */
#order-standard_cart .view-cart-items-header {
  background-color: var(--hk-ink, #0b1018);   /* white on this = 19.06:1 — AAA */
  color:            var(--hk-on-brand, #ffffff);
}
#order-standard_cart .view-cart-items {
  border-bottom-color: var(--hk-line-2, #c9ced6);
}

/* The remove-from-cart control. Stock is #444 going to #cc0000 on hover —
   4.32:1, which is under AAA for what is a text link at .75em. */
#order-standard_cart .btn-remove-from-cart {
  color: var(--hk-text-mute, #464d58);        /* 8.53:1 — AAA */
}
#order-standard_cart .btn-remove-from-cart:hover,
#order-standard_cart .btn-remove-from-cart:focus {
  color: var(--hk-danger-text, #941313);      /* 8.89:1 — AAA */
}

/* 4d. REDUCED MOTION
   The SPA animates its cart drawer and the classic cart animates its collapse
   panels. Neither carries information. */
@media (prefers-reduced-motion: reduce) {
  #order-standard_cart *,
  #nexus-root {
    animation-duration:        0.01ms !important;
    animation-iteration-count: 1      !important;
    transition-duration:       0.01ms !important;
    scroll-behavior:           auto   !important;
  }
}


/* ============================================================================
   WHAT CANNOT BE DONE FROM HERE

   1. STRUCTURE INSIDE THE SPA. The browse and domain-search steps are Vue
      components compiled into a 783 KB minified bundle and mounted in a shadow
      tree. There is no template to override, no slot, no hook. Reordering a
      field, changing a label, adding a trust badge next to the price: none of
      it is possible without replacing main.min.js, which would be forking the
      order form rather than theming it. Do not try.

   2. THE 60 RAW TAILWIND PALETTE REFERENCES. style.min.css reads
      var(--color-red-500), var(--color-blue-400) and 54 more like them, all
      declared in its own :host block. They back vueless's arbitrary-colour
      component API (`<UBadge color="red">`), so they are the SPA's escape
      hatch, not its theme, and remapping all 56 names would turn a red icon
      emerald and destroy the meaning the component was reaching for.

      They ARE reachable, by the section 3 route — a `#nexus-root { --color-
      red-500: ... }` rule would take. If a specific stock hue turns up
      somewhere it visibly does not belong once the cart is live, add that ONE
      name here with a note saying where it was seen. Do not pre-emptively
      remap the set.

   3. TYPE SCALE INSIDE THE SPA. --text-xs / --text-sm / --text-lg collide
      with Tailwind's names, and --spacing is the base unit every padding
      utility multiplies. Section 3 says why all four are left alone.

   4. THE ORDER FORM'S OWN COPY. This file is never fetched into the shadow
      tree — main.min.js resolves "../css/custom.css" against its own script
      URL, which is nexus_cart's. Anything written here that only makes sense
      inside the shadow tree (a :host rule, a rule matching an SPA class
      name) will never match anything. Only custom properties on :root and on
      #nexus-root cross the boundary.

   5. THE MARKETCONNECT PROMO TILES. standard_cart hardcodes #99bb3a, #56a2da,
      #f29f44, #4687FF and #7b7b7b on .mc-promo .btn-add. Those are Weebly,
      SpamExperts, SiteLock, NordVPN and friends wearing their own brands, and
      repainting a vendor's logo colour emerald is not ours to do. Left alone
      on purpose, not by omission.
   ============================================================================ */
