/* ==================================================================
   cart.v5.css  -  v5.1 styles for the cart and checkout flow only

   Loaded by:  cart_view.v5.1.asp
               cart_checkout.v5.1.asp
               account_checkout.v5.1.asp
               account_new.v5.1.asp
   Requires:   product-system.v5.css  (loaded first - this file only
               adds to it, and every selector still begins .zcp5)

   WHY A SEPARATE FILE
   The cart, checkout and new-account pages are the only self-contained
   funnel on the site: they lay out unlike every marketing page, they
   carry form controls and money, and nothing else links into their
   internals. Putting their rules in product-system.v5.css would mean
   every product page downloads checkout CSS it can never use, and a
   cart tweak would force a cache bump across two dozen pages.

   Same arrangement as learn.v5.css and tos.v5.css.

   THE RULES STILL APPLY
   1. Every selector begins .zcp5.
   2. Never style site chrome (header, footer, breadcrumb).
   3. Blanket element rules use :where() so they add no specificity and
      a component stating its own value always wins. product-system's
      .zcp-code-panel > h4 and a blanket .zcp5 .cart h4 would otherwise
      tie at (0,2,1) and load order would silently decide the colour.

   ?v= is bumped on every edit; the linkers are listed above.
   ================================================================== */


/* ------------------------------------------------------------------
   1. COMPACT HERO WITH ACTIONS

   .zcp-hero.compact is centred text, but .zcp-ctas is a plain flex row
   with no justification - it has only ever been used inside the full
   hero's left column, where flex-start is exactly right. The empty cart
   is the first page to put actions in a compact hero, so the buttons
   hugged the left edge under centred copy.

   Scoped to .compact: the full hero must keep flex-start.
   ------------------------------------------------------------------ */
.zcp5 .zcp-hero.compact .zcp-ctas{ justify-content:center; }

/*  The filled cart puts the panels in a bare .container straight after the
    hero, so the panel's top edge sat flush against the hero band. The empty
    cart does not need this - its hero is followed by a <section class="py-5">
    that brings its own padding - and the adjacent-sibling selector means
    only the container-after-a-hero case picks it up. */
.zcp5 .zcp-hero + .container{ padding-top:2.25rem; }


/* ------------------------------------------------------------------
   2. CART LINE ITEMS  (.cart-panel / .cart-line)

   The old line was a three-column flex - trash button, name, price -
   with the product's marketing bullets dumped underneath at full
   length. Those bullets are prodCartPromo, HTML held in PC_Products,
   so their CONTENT cannot be restructured from the page. But most of
   it repeats verbatim on every line (immediate download, pay by, free
   support); only the term and the file formats actually differ. With
   three items in the cart the same six bullets appeared three times
   and pushed the order total below the fold.

   So the promo keeps its own markup, untouched, inside a <details>
   that starts closed. Scannable by default, complete on demand, and
   no database change.

   Grid, not flex: name and price share row 1, and everything else
   spans the full width underneath, which flex cannot do without a
   second wrapper.
   ------------------------------------------------------------------ */
.zcp5 .cart-panel{
  background:#fff; border:1px solid #e6e9ef; border-radius:.9rem;
  padding:0; overflow:hidden;
  box-shadow:0 1px 2px rgba(15,23,42,.04), 0 8px 24px -16px rgba(15,23,42,.18);
}

/*  Both panels wear the Data Explorer's head: a navy strip flush to the
    panel edge, which is why .cart-panel is padding:0 + overflow:hidden and
    the padding lives on .cs-body instead. Two panels with the same head
    read as two halves of one thing rather than as a list beside a widget. */
.zcp5 .cs-head{ background:var(--zcp-navy, #091122); padding:.95rem 1.25rem; }
.zcp5 .cs-head h2{
  margin:0; color:#fff; font-size:1.15rem; font-weight:700;
  letter-spacing:-.01em;
}
.zcp5 .cs-body{ padding:1rem 1.25rem 1.15rem; }

/*  THE ACCENT RAIL
    Three items with identical weight and wildly uneven heights read as one
    blob - two tall lines carrying a disclosure and an upsell, one that is a
    single row. A hairline between them does not fix that, because the
    problem is not "where does one end", it is "these are all the same
    thing".

    A 4px rail in the product family's own colour fixes both at once: it
    draws the full height of the item, so a tall item and a short item are
    each visibly ONE object, and it carries the same colour that product's
    card uses in the catalog.

    Deliberately NOT a card per item: the multi-year upsell is already a
    bordered box, and a bordered card would put a box inside a box inside
    the panel. The rail adds separation with no extra depth, so the upsell
    stays the only raised thing in the list and keeps its meaning.

    The colour is derived from prodCartPage - see cartFamily() in the page.
    No family match means NO rail, never a default one: a wrong colour is a
    wrong claim about what kind of product someone is buying. */
.zcp5 .cart-line{
  display:grid; grid-template-columns:1fr auto; gap:.15rem 1.5rem;
  padding:1.4rem 0 1.4rem 1rem;
  margin-top:.65rem;
  border-top:1px solid #eef1f6;
  border-left:4px solid transparent;
}
.zcp5 .cart-line:first-of-type{ border-top:0; margin-top:0; }

.zcp5 .cart-line.f-zip { border-left-color:#AB2827; }
.zcp5 .cart-line.f-bdry{ border-left-color:#E67700; }
.zcp5 .cart-line.f-intl{ border-left-color:#7d9a2e; }
.zcp5 .cart-line.f-hist{ border-left-color:#5b6b8c; }
.zcp5 .cart-line.f-tool{ border-left-color:#0b6ea8; }

/*  Placement is explicit on all three of name / meta / price. It has to
    be: .cl-meta claims column 1, which pushes the NEXT auto-placed item
    (the price) into row 2 of column 2, and the price drifts a line below
    the product it belongs to. */
.zcp5 .cl-name{
  grid-column:1; grid-row:1;
  font-size:1.02rem; font-weight:650; line-height:1.35;
  color:#0f172a; text-decoration:none;
}
.zcp5 .cl-name:hover{ color:#1d4ed8; text-decoration:underline; }

/*  prodName arrives as "Product - term - seats". The product is what you
    scan for; the term and seat band are what you verify once you have
    found it. Splitting them lets the name be short and the qualifiers sit
    underneath at label weight, instead of one long string competing with
    the price. Products whose name has no " - " simply have no meta line. */
.zcp5 .cl-meta{
  grid-column:1; grid-row:2; margin:.15rem 0 0;
  font-size:.82rem; color:#64748b;
}

.zcp5 .cl-price{
  grid-column:2; grid-row:1 / span 2; align-self:start;
  text-align:right; white-space:nowrap;
}
.zcp5 .cl-amt{
  font-size:1.12rem; font-weight:700; color:#0f172a;
  font-variant-numeric:tabular-nums;
}
.zcp5 .cl-save{
  display:block; margin-top:.2rem;
  font-size:.78rem; font-weight:650; color:#15803d;
}

/*  Remove is destructive and belongs at the visual weight of an undo,
    not of the primary action. The old page gave it a filled red circle
    on every row AND a full-width blood-red bar at the foot - together
    the loudest thing on a page whose job is to reach checkout. */
/*  block, not inline-block: only the lines that happen to carry a
    .cl-save get pushed onto their own row by it. Inline, Remove sat
    beside the amount on the lines without one and read as part of the
    price. */
.zcp5 .cl-remove{
  display:block; margin-top:.45rem;
  font-size:.78rem; color:#94a3b8; text-decoration:none;
}
.zcp5 .cl-remove:hover,
.zcp5 .cl-remove:focus-visible{ color:#b91c1c; text-decoration:underline; }

/*  A product with no configurator detail and no prodCartPromo renders an
    empty .cl-body. Left in flow it reserved a row's worth of space under
    a one-line item. */
.zcp5 .cl-body{ grid-column:1 / -1; grid-row:3; }
.zcp5 .cl-body:empty{ display:none; }
.zcp5 .cl-sub{ margin:.4rem 0 0; font-size:.85rem; color:#475569; }
.zcp5 .cl-sub b{ color:#334155; font-weight:650; }

.zcp5 .cl-incl{ margin-top:.5rem; }
.zcp5 .cl-incl > summary{
  cursor:pointer; width:fit-content;
  font-size:.8rem; font-weight:600; color:#5b6b82;
}
.zcp5 .cl-incl > summary:hover{ color:#1d4ed8; }
.zcp5 .cl-incl[open] > summary{ margin-bottom:.3rem; }
.zcp5 .cl-incl ul{ margin:0; padding-left:1.15rem; }
.zcp5 .cl-incl li{ font-size:.84rem; line-height:1.6; color:#475569; }
.zcp5 .cl-incl p{ margin:0 0 .2rem; font-size:.84rem; color:#475569; }


/* ------------------------------------------------------------------
   3. MULTI-YEAR UPSELL  (.cl-upsell)

   Was a block with a 100px line-art illustration, a Caveat-script
   heading and an ORANGE button - a third button colour on a page where
   green already means go and red means remove. Repeated per item, it
   outweighed the product it was attached to.

   Now one quiet strip: what it is, why, the control, the action. The
   <select> keeps its onChange auto-submit, so the button stays the
   no-JS fallback it always was.
   ------------------------------------------------------------------ */
.zcp5 .cl-upsell{
  grid-column:1 / -1; grid-row:4;
  display:flex; flex-wrap:wrap; align-items:center; gap:.5rem .8rem;
  margin:.75rem 0 0; padding:.6rem .85rem;
  border:1px dashed #cdd7e5; border-radius:.55rem; background:#f8fafc;
}
.zcp5 .cl-upsell .u-label{ font-size:.84rem; font-weight:700; color:#0f172a; }
.zcp5 .cl-upsell .u-why{ flex:1 1 11rem; font-size:.82rem; color:#64748b; }
.zcp5 .cl-upsell select{
  max-width:100%; padding:.34rem .5rem; font-size:.82rem;
  border:1px solid #cbd5e1; border-radius:.4rem; background:#fff; color:#0f172a;
}
.zcp5 .cl-upsell button{
  padding:.4rem .85rem; font-size:.82rem; font-weight:650;
  color:#1d4ed8; background:#fff;
  border:1.5px solid #1d4ed8; border-radius:.4rem; cursor:pointer;
}
.zcp5 .cl-upsell button:hover{ background:#1d4ed8; color:#fff; }


/* ------------------------------------------------------------------
   4. PANEL FOOT  (.cart-foot)
   Continue shopping is the real secondary action. Checkout is NOT
   repeated here - it lives in the summary rail, which is sticky, so it
   stays on screen the whole way down anyway. That duplicate green
   button at the foot of the item list existed to solve a scrolling
   problem that position:sticky solves properly.
   ------------------------------------------------------------------ */
.zcp5 .cart-foot{
  display:flex; flex-wrap:wrap; align-items:center;
  justify-content:space-between; gap:.75rem;
  margin-top:1.1rem; padding-top:1rem; border-top:1px solid #eef1f6;
}
.zcp5 .cart-foot .cf-clear{ font-size:.8rem; color:#94a3b8; text-decoration:none; }
.zcp5 .cart-foot .cf-clear:hover{ color:#b91c1c; text-decoration:underline; }


/* ------------------------------------------------------------------
   5. SUMMARY RAIL  (.cart-summary)

   Sticky, so Checkout stays reachable however long the cart runs.

   The item count was a RED pill, which on a checkout page reads as an
   error rather than as "3 things".
   ------------------------------------------------------------------ */
/*  The Data Explorer's panel pattern, reused: white panel, overflow
    hidden, a navy strip across the top carrying the heading. It gives the
    money column an anchor without turning the whole rail dark - which
    would have cost the green Checkout button its contrast and put five
    payment logos with white backgrounds on a navy field. */
/*  #top-nav is position:sticky at top:0 and measures 82px, so a rail
    stuck at top:1rem slides UNDER the site header. 6rem clears the nav
    with a little air; the max-height keeps a long rail scrollable instead
    of running off the bottom on a short viewport. */
.zcp5 .cart-summary{
  position:sticky; top:6rem;
  max-height:calc(100vh - 7.5rem); overflow:auto;
}

.zcp5 .cs-row{
  display:flex; justify-content:space-between; align-items:baseline; gap:1rem;
  padding:.32rem 0; font-size:.92rem; color:#475569;
}
.zcp5 .cs-row > span:last-child{
  color:#0f172a; font-variant-numeric:tabular-nums; text-align:right;
}
.zcp5 .cs-row .cs-note{ font-size:.82rem; color:#64748b; font-variant-numeric:normal; }
.zcp5 .cs-row.cs-discount > span:last-child{ color:#15803d; font-weight:650; }
.zcp5 .cs-coupon{ display:block; font-size:.78rem; color:#64748b; }

.zcp5 .cs-rule{ margin:.7rem 0; border:0; border-top:1px solid #e6e9ef; opacity:1; }

.zcp5 .cs-total{
  display:flex; justify-content:space-between; align-items:baseline; gap:1rem;
  font-size:1.05rem; font-weight:700; color:#0f172a;
}
.zcp5 .cs-total .cs-amt{ font-size:1.5rem; font-variant-numeric:tabular-nums; }

.zcp5 .cart-summary .zcp-cta{
  display:block; width:100%; text-align:center; margin:.9rem 0 .2rem;
}
.zcp5 .cs-secure{
  display:flex; align-items:center; justify-content:center; gap:.4rem;
  font-size:.78rem; color:#64748b; margin-bottom:.9rem;
}
.zcp5 .cs-pay{ text-align:center; }
.zcp5 .cs-pay h3{
  font-size:.78rem; font-weight:650; letter-spacing:.06em;
  text-transform:uppercase; color:#94a3b8; margin:.9rem 0 .5rem;
}
/*  These were rendering 206px wide and stacked, which made the logos the
    second-biggest thing in the rail after the total. They are reassurance:
    you check they are there, you do not read them. */
.zcp5 .cs-pay img{ max-width:145px; width:100%; height:auto; }
.zcp5 .cs-pay > div{ margin:0 !important; }


@media (max-width: 767.98px){
  .zcp5 .cart-summary{ position:static; max-height:none; overflow:visible; }

  /*  Collapsing to one column needs the explicit placements released too.
      .cl-price keeps grid-column:2, which creates an IMPLICIT second
      column, and `grid-column:1 / -1` only reaches the last EXPLICIT line
      - so the upsell and detail spanned ~169px of the 289px available
      while the price kept a phantom column beside them. */
  .zcp5 .cart-line{ grid-template-columns:1fr; }
  .zcp5 .cl-name,
  .zcp5 .cl-meta,
  .zcp5 .cl-price,
  .zcp5 .cl-body,
  .zcp5 .cl-upsell{ grid-column:1; grid-row:auto; }
  .zcp5 .cl-price{ text-align:left; }
  .zcp5 .cl-remove{ display:inline-block; margin-left:.75rem; }
}


/* ------------------------------------------------------------------
   6. ACCOUNT GATE  (account_checkout.v5.1.asp)

   Sign in on one side, a 25-field registration form on the other. The
   two columns reuse .cart-panel and .cs-head so the gate looks like the
   cart it came from rather than like a different application.

   The columns are wildly unequal - login is 5 fields, registration is
   25 - so the short side gets the aside below it rather than being
   stretched to match. Stretching a 5-field form to 1500px is how the
   old page ended up with half a screen of nothing.
   ------------------------------------------------------------------ */
.zcp5 .ac-why{
  margin:0 0 1.1rem; padding:.7rem .85rem;
  font-size:.84rem; line-height:1.55; color:#475569;
  background:#f8fafc; border-left:3px solid #cbd5e1; border-radius:.35rem;
}

/*  A password reset is a recovery path, not the second thing you might
    want to do here. It was a full-width blue button directly under a
    green one, which made the pair read as a choice. */
.zcp5 .ac-alt{ margin:-.4rem 0 .3rem; text-align:center; }
.zcp5 .ac-alt a{ font-size:.82rem; color:#64748b; text-decoration:underline; }
.zcp5 .ac-alt a:hover{ color:#1d4ed8; }

.zcp5 .ac-aside{ margin-top:1.1rem; }

/*  What the visitor is actually signing in FOR. The old page never
    mentioned the cart on the one screen that interrupts the purchase. */
.zcp5 .ac-cart{
  display:flex; align-items:center; gap:.85rem; flex-wrap:wrap;
  padding:.9rem 1rem; margin-bottom:1rem;
  background:#fff; border:1px solid #e6e9ef; border-radius:.7rem;
  box-shadow:0 1px 2px rgba(15,23,42,.04);
}
.zcp5 .ac-cart .acc-n{
  flex:none; display:grid; place-items:center;
  width:2.4rem; height:2.4rem; border-radius:999px;
  background:var(--zcp-navy, #091122); color:#fff;
  font-size:1.05rem; font-weight:700; font-variant-numeric:tabular-nums;
}
.zcp5 .ac-cart > div{ flex:1 1 10rem; min-width:0; }
.zcp5 .ac-cart b{ display:block; font-size:.9rem; color:#0f172a; }
.zcp5 .ac-cart p{ margin:.15rem 0 0; font-size:.8rem; color:#64748b; }

.zcp5 .ac-assure{ list-style:none; margin:0; padding:0; }
.zcp5 .ac-assure li{
  display:flex; align-items:flex-start; gap:.6rem;
  padding:.4rem 0; font-size:.84rem; line-height:1.5; color:#475569;
}
.zcp5 .ac-assure i{ color:var(--zcp-go, #3d9c40); margin-top:.2rem; flex:none; }

/*  .zcp-cta is written for <a>; these are <button>s, so they need the
    element defaults knocked out or the browser paints its own chrome. */
.zcp5 button.zcp-cta{
  border:0; cursor:pointer; font:inherit;
  font-size:.95rem; font-weight:700;
}
.zcp5 .w-100.zcp-cta{ display:block; width:100%; text-align:center; }

/*  The password rules render as .note.note-primary, which the site
    stylesheet paints as a filled blue panel. On a form whose own inputs
    are white boxes, a saturated blue block reads as an ERROR the user has
    already made, not as guidance about a field they have not filled in.
    Restyled here rather than in the markup, because .note-primary is
    shared and this scope only reaches the four cart-flow pages. */
.zcp5 .note.note-primary{
  background:transparent; border:0; border-left:3px solid #cbd5e1;
  border-radius:0; padding:.3rem 0 .3rem .7rem; margin:-.4rem 0 1rem;
  color:#64748b; font-size:.8rem; line-height:1.5;
}


/* ------------------------------------------------------------------
   7. CHECKOUT  (cart_checkout.v5.1.asp)
   ------------------------------------------------------------------ */

/*  "Change Billing Info" was a filled BLUE button floated against the
    heading, on a page whose one real action is the green Place Order.
    Correcting an address you are only being shown for confirmation is a
    correction, not a second call to action. */
.zcp5 .co-change{
  float:right; font-size:.82rem; color:#1d4ed8; text-decoration:underline;
}
.zcp5 .co-change:hover{ color:#0f172a; }

/*  TERMS OF SERVICE is a legal gate and must be unmissable.

    It shared the .note.note-primary class with the password hint on the
    account page, so quietening that hint (section 6) washed this out too -
    pale checkboxes on a white field, which is the LAST thing that should
    be hard to see on a page about to take payment. #tbl-tos wins on
    specificity and puts the weight back.

    NOTE: the agreement text is not wrapped in <label for>, so only the box
    itself is clickable, not the sentence. Not fixed here - the text
    contains the TOS modal link, and wrapping it in a label would make
    opening the terms also tick the box. Wants markup surgery, not CSS. */
.zcp5 #tbl-tos .note.note-primary{
  background:#f8fafc; border:1px solid #dbe3ec;
  border-left:4px solid var(--zcp-accent, #0ea5e9);
  border-radius:.5rem; padding:.9rem 1.1rem; margin:0;
  color:#334155; font-size:.88rem; line-height:1.9;
}
.zcp5 #tbl-tos .form-check-input{
  width:1.15rem; height:1.15rem; margin-right:.15rem;
  border:1.5px solid #64748b; background-color:#fff;
  vertical-align:-.2em; cursor:pointer;
}
.zcp5 #tbl-tos .form-check-input:checked{
  background-color:var(--zcp-go, #3d9c40); border-color:var(--zcp-go, #3d9c40);
}
.zcp5 #tbl-tos .form-check-input:focus-visible{
  outline:2px solid var(--zcp-accent, #0ea5e9); outline-offset:2px;
}

/*  SECTION PANELS  (.co-sec)

    Products, billing, payment and terms each become their own panel with
    the navy head. They carry NO body wrapper - the head bleeds to the
    panel edge on a negative margin instead, clipped by .cart-panel's
    overflow:hidden. That keeps every section div-neutral, which matters
    on a page where the whole column sits inside one <form>: an extra
    wrapper means an extra close, and a mis-placed close drops a hidden
    input out of the POST. */
.zcp5 .co-stack{ margin:0; }
.zcp5 .co-sec{ padding:0 1.25rem 1.2rem; }
.zcp5 .co-sec > .cs-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:1rem;
  margin:0 -1.25rem 1.1rem;
}
.zcp5 .co-sec > .cs-head .co-change{
  float:none; color:#7dd3fc; font-size:.8rem; text-decoration:underline;
}
.zcp5 .co-sec > .cs-head .co-change:hover{ color:#fff; }

/*  The checkout list is a CONFIRMATION, not a shopping surface: no
    disclosure, no upsell, tighter rhythm. The accent rail and the
    title/meta split carry over from the cart so the two read as one
    flow. */
.zcp5 .co-line{ padding:.95rem 0 .95rem .9rem; margin-top:.5rem; }
.zcp5 .co-line .cl-name{ font-size:.97rem; }
.zcp5 .co-line .cl-amt{ font-size:1.05rem; }
.zcp5 .co-line .cl-body{ margin-top:.1rem; }

.zcp5 .co-place{ padding:0 1.25rem; }
.zcp5 .co-place .zcp-cta{ display:block; width:100%; text-align:center; }

/*  Billing reads as a confirmation list, so the labels recede and the
    values carry the weight - the reverse of a form. */
.zcp5 #tbl-billing .frm-group{
  display:flex; gap:.5rem; padding:.18rem 0; font-size:.88rem;
}
.zcp5 #tbl-billing .frm-group label{
  flex:none; min-width:6.5rem; color:#64748b; font-weight:400; margin:0;
}

/* ------------------------------------------------------------------
   8. PAYMENT METHOD  (.co-pay)

   The Data Explorer's edition switcher, reused: the native radios stay
   in the DOM and are only visually replaced, so keyboard, screen
   readers and the toggleCardInfo() show/hide all keep working.

   The win beyond looks is the TARGET. As a bare radio list the hit area
   was a 16px circle; each option is now a whole pill. That also made a
   latent bug visible - the American Express label pointed at the
   Mastercard input, so clicking the words selected the wrong card.
   ------------------------------------------------------------------ */
.zcp5 .co-pay{ display:flex; flex-direction:column; gap:.85rem; }

/*  Two groups, each labelled. Card types and non-card types are a real
    distinction - pay now with a card, or pay some other way - so it is
    worth stating rather than leaving to however the pills happen to wrap
    at a given width. */
.zcp5 .co-pay-set{ display:flex; flex-wrap:wrap; align-items:center; gap:.45rem; }
.zcp5 .co-pay-set > div{ margin:0; }
.zcp5 .co-pay-lbl{
  flex:0 0 100%; margin-bottom:.1rem;
  font-size:.7rem; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; color:#94a3b8;
}
.zcp5 .co-pay input[type="radio"]{
  position:absolute; opacity:0; width:1px; height:1px;
}
.zcp5 .co-pay input[type="radio"] + label{
  display:inline-block; margin:0; padding:.45rem .9rem;
  border:1px solid #cbd5e1; border-radius:999px; background:#fff;
  font-size:.85rem; font-weight:600; color:#334155; cursor:pointer;
  transition:background .12s, border-color .12s, color .12s;
}
/*  Hover fills rather than only darkening the hairline - on a row of
    outlined pills a border shift alone is nearly invisible, and this is a
    control people hunt for. No per-brand colour: the family accents
    already use colour to mean "which product", and reusing it here for
    "which card" would make the same language mean two things. */
.zcp5 .co-pay input[type="radio"] + label:hover{
  background:#eef2f7; border-color:#94a3b8; color:#0f172a;
}
.zcp5 .co-pay input[type="radio"]:checked + label:hover{
  background:#16233d; border-color:#16233d; color:#fff;
}
.zcp5 .co-pay input[type="radio"]:checked + label{
  background:var(--zcp-navy, #091122); border-color:var(--zcp-navy, #091122);
  color:#fff;
}
.zcp5 .co-pay input[type="radio"]:focus-visible + label{
  outline:2px solid var(--zcp-accent, #0ea5e9); outline-offset:2px;
}

/*  The notes toggleCardInfo() slides in for PayPal / mail-in / invoice.
    .note-info is a filled panel from the site stylesheet; here it is a
    quiet aside, because it explains what happens next rather than
    warning about anything. */
.zcp5 .note.note-info{
  background:#f8fafc; border:0; border-left:3px solid var(--zcp-accent, #0ea5e9);
  border-radius:.35rem; padding:.7rem .9rem; margin:0;
  color:#475569; font-size:.85rem; line-height:1.55;
}
.zcp5 .note.note-info b{ color:#0f172a; }
/*  Same clearance as #CardInfo: whichever of the three panels is
    showing, it sits the same distance below the payment pills, so the
    block does not jump as you switch method. */
.zcp5 #PayPalInfo, .zcp5 #MailinInfo{ margin:1.35rem 0 1.6rem !important; }

/*  A month, a year and 3-4 digits do not need three full-width rows. */
.zcp5 .co-card3{
  display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:0 .85rem;
}
.zcp5 .co-card3 .form-group{ width:100%; min-width:0; }
.zcp5 .co-card3 select,
.zcp5 .co-card3 input{ min-width:0; }

@media (max-width: 575.98px){
  .zcp5 .co-card3{ grid-template-columns:1fr 1fr; }
  .zcp5 .co-card3 .form-group:last-child{ grid-column:1 / -1; }
}

/*  #CardInfo carries Bootstrap's my-5 (3rem top AND bottom), which left a
    dead band under the card row before the next panel. jQuery slideUp/Down
    animates height only, so the margin is not part of the toggle and can
    be trimmed safely. */
.zcp5 #CardInfo{ margin:1.35rem 0 0 !important; }
/*  Not less: these are NOTCHED labels that sit ABOVE their input and
    overlap the box, so too small a top margin runs 'Credit Card
    Number' straight into the payment pills above it. */

/*  Card Code shares a third of the row with a label, an icon and the
    help link, so the input needs to claim the leftover rather than sit
    at its size attribute's width. */
.zcp5 .co-card3 .form-group input[name="frmCVV2"]{ flex:1 1 auto; width:auto; }
.zcp5 .co-card3 .form-group > a{ flex:none; margin-left:.4rem; }
.zcp5 .co-card3 select{ flex:1 1 auto; }

/*  PO Number now closes the payment panel rather than opening it, so it
    reads as the optional note-to-self it is. */
.zcp5 #tbl-payment .form-group:has(#frmPONumber){ margin-top:.5rem; }

/*  Place Order is the last action in the funnel and should look like it.
    Set here rather than as an inline style: this page is being actively
    de-inlined, and a style attribute would also outrank the stylesheet,
    so the next person adjusting the button would edit the CSS and see
    nothing happen. */
.zcp5 .co-place .zcp-cta{
  padding:1rem 1.5rem;
  font-size:1.12rem; font-weight:700; letter-spacing:.01em;
  border-radius:.6rem;
  box-shadow:0 6px 18px -8px rgba(61,156,64,.7);
}
.zcp5 .co-place .zcp-cta i{ margin-right:.1rem; }

/* ------------------------------------------------------------------
   9. VALIDATION FEEDBACK  (cart.v5.js)

   Errors are shown AT the field, not as a toast and not only as a
   summary at the top. A toast leaves the screen while the broken field
   stays broken, and a summary far from the input makes the customer
   hunt. The field gets a red border, the message sits directly beneath
   it, and the first offender is scrolled to and focused.
   ------------------------------------------------------------------ */
.zcp5 .co-invalid,
.zcp5 input.co-invalid,
.zcp5 select.co-invalid{
  border-color:#dc2626 !important;
  box-shadow:0 0 0 3px rgba(220,38,38,.12) !important;
}
.zcp5 input[type="checkbox"].co-invalid{
  outline:2px solid #dc2626; outline-offset:2px; box-shadow:none !important;
}
.zcp5 .co-pay.co-invalid{
  border:0 !important; box-shadow:none !important;
}

.zcp5 .co-fieldmsg{
  display:flex; align-items:flex-start; gap:.4rem;
  margin:-.6rem 0 1rem; padding:0;
  font-size:.82rem; font-weight:600; line-height:1.45; color:#b91c1c;
}
.zcp5 .co-fieldmsg::before{
  content:"!"; flex:none;
  display:inline-grid; place-items:center;
  width:1.05rem; height:1.05rem; margin-top:.05rem;
  border-radius:999px; background:#dc2626; color:#fff;
  font-size:.72rem; font-weight:700;
}
.zcp5 .co-pay + .co-fieldmsg{ margin:.2rem 0 0; }
.zcp5 #tbl-tos .co-fieldmsg{ margin:0 0 .7rem; }
.zcp5 #tbl-tos .note.co-invalid{
  border-left-color:#dc2626; box-shadow:none !important;
}

/*  Inside .co-card3 a message is a grid ITEM, so it took the next column
    and pushed Exp. Year out of place. Span the full row instead: the
    field keeps its red border, the message sits under the row. */
.zcp5 .co-card3 + .co-fieldmsg{ margin:-.6rem 0 .9rem; }

/* ------------------------------------------------------------------
   10. SUBMITTING STATE  (#chkout, disabled #Submit)

   disableForm() disables every submit button and reveals #chkout. The
   server keys the order off the hidden action=go input, not the button's
   name, so disabling it costs the POST nothing.
   ------------------------------------------------------------------ */

/*  A disabled Place Order must still read as "working", not as "broken".
    Keeps the green, drops the lift and the pointer. */
.zcp5 .co-place .zcp-cta:disabled,
.zcp5 .co-place .zcp-cta[disabled]{
  opacity:.65; cursor:progress; box-shadow:none; filter:saturate(.85);
}

/*  Was a Bootstrap alert-warning - amber, which reads as "something is
    wrong" at the exact moment the payment is going through. This is a
    progress notice, so it is calm and carries a spinner. */
.zcp5 #chkout{
  display:flex !important; align-items:center; gap:.7rem;
  margin:.9rem 0 0; padding:.85rem 1rem;
  background:#f8fafc; border:1px solid #dbe3ec;
  border-left:4px solid var(--zcp-go, #3d9c40); border-radius:.55rem;
  color:#334155; font-size:.88rem; line-height:1.5;
}
.zcp5 #chkout[style*="display:none"],
.zcp5 #chkout[style*="display: none"]{ display:none !important; }

.zcp5 #chkout::before{
  content:""; flex:none;
  width:1.15rem; height:1.15rem; border-radius:999px;
  border:2px solid #cbd5e1; border-top-color:var(--zcp-go, #3d9c40);
  animation:co-spin .7s linear infinite;
}
@keyframes co-spin{ to{ transform:rotate(360deg); } }

@media (prefers-reduced-motion: reduce){
  .zcp5 #chkout::before{ animation:none; border-top-color:#cbd5e1; }
}

/*  Escape aborts the browser's request, not the order. The server has it
    and will finish. So the notice escalates to a warning and the button
    stays disabled - the one thing the customer must NOT do is submit
    again, which is exactly what a re-enabled button would invite. */
.zcp5 #chkout.is-held{
  background:#fffbeb; border-color:#f5d9a0; border-left-color:#c98a17;
}
.zcp5 #chkout.is-held::before{
  animation:none; border-color:#f5d9a0; border-top-color:#c98a17;
}
/*  #chkout is a flex row (spinner + text), so an appended message becomes
    a THIRD flex item and lands beside the text. Force it onto its own
    line, indented past the spinner so it reads as a continuation. */
.zcp5 #chkout{ flex-wrap:wrap; }
.zcp5 #chkout .co-hold{
  flex:0 0 100%; margin:.5rem 0 0 1.85rem;
  font-size:.86rem; font-weight:600; color:#92400e;
}
.zcp5 #chkout.is-held > .co-hold{ display:block; }

/*  The order-history link has to stay legible on the amber hold panel. */
.zcp5 #chkout .co-hold a{
  color:#7c2d12; text-decoration:underline; text-underline-offset:2px;
}
.zcp5 #chkout .co-hold a:hover{ color:#431407; }

/* ------------------------------------------------------------------
   11. SUMMARY FINE PRINT  (.cs-terms)
   Renewal and delivery terms, stated where the money is rather than
   left to the product page.
   ------------------------------------------------------------------ */
.zcp5 .cs-terms{
  margin:.55rem 0 0; padding-top:.55rem;
  border-top:1px solid #eef1f6;
  font-size:.76rem; line-height:1.5; color:#64748b;
}
.zcp5 .cs-secure + .cs-terms{ border-top:0; padding-top:0; text-align:center; }

/*  The amount rides on the button, so it needs room to breathe. */
.zcp5 .co-place .zcp-cta{ white-space:normal; }

/* ------------------------------------------------------------------
   12. SERVER-SIDE MESSAGES

   The msg=1..10 responses render as bare Bootstrap alerts above the
   form - a different visual language from the client-side validation
   the customer just saw. Same shape, same weight, same icon.
   ------------------------------------------------------------------ */
.zcp5 .container > .alert-danger,
.zcp5 .container > .alert-warning,
.zcp5 .cs-body > .alert-warning{
  display:flex; align-items:flex-start; gap:.6rem;
  max-width:none; margin:1.4rem 0 0; padding:.9rem 1.1rem;
  border:1px solid #f0c4c4; border-left:4px solid #dc2626;
  border-radius:.55rem; background:#fef4f4;
  font-size:.9rem; font-weight:600; line-height:1.5; color:#b91c1c;
}
.zcp5 .container > .alert-danger::before,
.zcp5 .container > .alert-warning::before,
.zcp5 .cs-body > .alert-warning::before{
  content:"!"; flex:none;
  display:inline-grid; place-items:center;
  width:1.15rem; height:1.15rem; margin-top:.1rem;
  border-radius:999px; background:#dc2626; color:#fff;
  font-size:.78rem; font-weight:700;
}
.zcp5 .container > .alert-danger a,
.zcp5 .container > .alert-warning a{ color:#7f1d1d; text-decoration:underline; }

/*  Coupon notices in the rail are informational, not failures. */
.zcp5 .cs-body > .alert-warning{
  border-color:#f5d9a0; border-left-color:#c98a17;
  background:#fffbeb; color:#92400e; font-weight:500;
}
.zcp5 .cs-body > .alert-warning::before{ background:#c98a17; }

/* ==========================================================================
   MISSING BILLING ADDRESS
   --------------------------------------------------------------------------
   An account can reach checkout with no billing address: the API signup
   creates accounts with those columns empty, and the customer then comes here
   to buy. They used to fill in a card and crash at the INSERT. Now the page
   says so up front, points at the fix, and will not let them submit.
   ========================================================================== */
.zcp5 .co-need-billing{
  margin:0 0 1rem; padding:1rem 1.15rem;
  border:1px solid #f5c2c7; border-left:4px solid #dc2626;
  border-radius:8px; background:#fff5f5; color:#7f1d1d;
}
.zcp5 .co-need-billing h3{
  margin:0 0 .35rem; font-size:1rem; font-weight:700; color:#7f1d1d;
}
.zcp5 .co-need-billing p{ margin:0 0 .85rem; font-size:.92rem; line-height:1.5; }
.zcp5 .co-need-billing .co-fix{
  display:inline-flex; align-items:center; gap:.5rem;
  padding:.7rem 1.15rem; border-radius:8px;
  background:#dc2626; color:#fff; font-weight:600; text-decoration:none;
}
.zcp5 .co-need-billing .co-fix:hover{ background:#b91c1c; color:#fff; }
.zcp5 .co-need-billing .co-fix:focus-visible{ outline:3px solid #7f1d1d; outline-offset:2px; }

/*  The individual field that is empty, in the billing readout. */
.zcp5 .co-missing{
  display:inline-block; padding:.1rem .45rem; border-radius:4px;
  background:#fee2e2; color:#b91c1c; font-size:.8rem; font-weight:700;
  letter-spacing:.02em; text-transform:uppercase;
}

/*  Place Order, when it cannot be used yet. Kept visible rather than hidden
    so the page still reads as a checkout - it just cannot be completed. */
.zcp5 .zcp-cta:disabled,
.zcp5 .zcp-cta[disabled]{
  opacity:.45; cursor:not-allowed; filter:grayscale(.55);
}
.zcp5 .co-place-blocked{
  margin:.6rem 0 0; font-size:.86rem; line-height:1.5; color:#7f1d1d; text-align:center;
}
