/* ============================================================================
   cart.css — the basket, and the one control that puts things in it
   ----------------------------------------------------------------------------
   Loaded on exactly two pages:

     /cart          the basket itself                    layouts.app
     /store/{slug}  for .crt-added, the inline answer     layouts.app
                    the add-to-cart form paints without
                    reloading the product page

   BOTH ARE PUBLIC PAGES, so nothing here may lean on dashboard.css tokens —
   they are declared on .dash-body, they do not exist out here, and a var() with
   no declaration anywhere in the chain makes the whole declaration invalid at
   computed-value time. The rule then vanishes with no error and no 404 behind
   it; the only symptom is a control that looks unfinished. Same discipline
   changelog.css states at the top of itself, and for the same reason: that file
   is loaded on this product page too.

   EVERY CLASS IS PREFIXED `crt-`. theme.css, store.css and product.css are the
   operator's original design and are not editable — the store and product pages
   are ported from it and must not be restyled — so nothing here may collide
   with a name any of them owns. The prefix is what guarantees that mechanically
   rather than by inspection.

   THE PALETTE IS THE SITE'S, restated as --crt-* properties on the components
   themselves rather than assumed from an ancestor:

     bg #0F0E0E · surface #141313 · raised #1A1919 · border #262424
     muted #8A8585 · secondary #C9C5C5 · white #FFF · accent #EA9C22
     success #22C55E · warning #F97316 · danger #EF4444

   NO HORIZONTAL SCROLL AT ANY WIDTH. Measured at 1440, 768, 430 and 360. The
   line grid restacks twice on the way down and every text cell is
   min-width-0'd, because a grid track defaults to min-content and one long
   product name is all it takes to push a row wider than its container and the
   document wider than the viewport — invisible on this machine and a scrollbar
   on somebody's phone.
   ========================================================================== */

/* THE TOKENS ARE DECLARED ON EVERY BLOCK THAT CAN STAND ALONE, not once on a
   page wrapper. .crt-added is the reason this rule is written this way: it
   renders on the PRODUCT page, inside .pricing-card, where there is no
   .crt-page above it and never will be. A block that inherited its colours from
   a wrapper it does not have would render as bare text with no border, which is
   precisely the failure mode described above. If a crt- block is reused
   somewhere new, check that it inherits these from something. */
.crt-page,
.crt-panel,
.crt-line,
.crt-empty,
.crt-note,
.crt-added,
.crt-crumbs {
    --crt-bg:        #0F0E0E;
    --crt-surface:   #141313;
    --crt-raised:    #1A1919;
    --crt-border:    #262424;
    --crt-muted:     #8A8585;
    --crt-secondary: #C9C5C5;
    --crt-accent:    #EA9C22;
    --crt-success:   #22C55E;
    --crt-warning:   #F97316;
    --crt-danger:    #EF4444;

    --crt-radius:    16px;
    --crt-radius-sm: 10px;
}


/* ── The hero ───────────────────────────────────────────────────────────────
   section.hero.store (theme.css:490) is the short hero every informational
   page uses — 180px top, 100px bottom, and no min-height:100vh. It is reused
   unchanged, with .crt-hero added purely as a hook for the one override below.

   THE SPECIFICITY HERE IS NOT DECORATION. theme.css:369 declares
   `section.hero .hero-main .hero-subtitle { margin-bottom: 40px }`, which is
   (0,3,1) — a bare `.crt-hero .hero-main .hero-subtitle` is (0,3,0) and LOSES
   to it regardless of file order. Every other page in the site puts something
   after the subtitle (buttons, feature chips) that absorbs the 40px; this page
   puts nothing, so unhandled it becomes 140px of empty screen between the
   sentence and the first cart line. Written as `section.hero.crt-hero …` it is
   (0,4,1) and wins on its own merits, with no !important. */
section.hero.crt-hero .hero-main .hero-subtitle {
    margin-bottom: 0;
}

/* .hero-main is max-width:600px inside a flex COLUMN (theme.css:334), and a
   column's cross axis is horizontal — so without this the 600px block sits
   hard against the left edge of a 1160px container while its own text is
   centred inside it, which reads as a typo rather than a layout. /store gets
   away with it because .hero-content there holds a second, full-width child. */
section.hero.crt-hero .hero-content {
    align-items: center;
}

/* Breadcrumbs, under our own name.
   `.breadcrumb` is declared in store.css and product.css and in NEITHER of the
   two stylesheets this page loads, so the shared class would render as three
   unstyled inline elements here. /changelog has exactly that bug today. */
.crt-crumbs {
    position: relative;
    z-index: 5;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 28px;
    font-size: 13.5px;
    color: var(--crt-muted);
}

.crt-crumbs a {
    color: var(--crt-secondary);
    text-decoration: none;
    transition: color .2s ease;
}

.crt-crumbs a:hover { color: var(--crt-accent); }
.crt-crumbs [aria-current] { color: #FFFFFF; }


/* ── The page ───────────────────────────────────────────────────────────────
   min-height keeps the footer off the middle of the screen when the cart holds
   one line on a tall monitor. 470px is the measured height of the hero above
   it, so hero + content ≳ one viewport — the same arithmetic .info-section
   uses in enhancements.css, and the same reason. */
.crt-page {
    padding: 0 0 96px;
    background: var(--crt-bg);
    min-height: calc(100vh - 470px);
}

/* TWO COLUMNS, AND THE SUMMARY IS THE FIXED ONE. A basket line is
   unpredictably wide (a product name can be two words or nine) and a total is
   not, so the flexible track goes to the lines. minmax(0, 1fr) rather than 1fr
   because a grid track's automatic minimum is min-content: with plain 1fr, one
   unbreakable product name widens the track past the container and takes the
   document with it. This is the single most common source of the horizontal
   scrollbar the brief forbids. */
.crt-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 344px;
    gap: 24px;
    align-items: start;
}

/* A grid ITEM is also a grid CONTAINER's child with an automatic minimum of
   min-content, so the same guard is needed one level down or a long line inside
   .crt-main pushes the whole two-column grid wide. */
.crt-main,
.crt-side {
    min-width: 0;
}

.crt-side {
    display: flex;
    flex-direction: column;
    gap: 16px;
    /* The summary follows the lines down a long cart. .crt-layout is
       align-items:start, which is what leaves the item short enough to have
       somewhere to travel; stretched, sticky would have no effect at all.
       96px clears the fixed navbar (68px) with room to breathe. */
    position: sticky;
    top: 96px;
}


/* ── A panel ────────────────────────────────────────────────────────────────
   The shared surface: the line list, the promo box and the summary are all one
   of these, so the three read as one design rather than three widgets that
   happen to share a page. */
.crt-panel {
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius);
    background: var(--crt-surface);
    overflow: hidden;
}

/* THERE IS NO `.crt-panel + .crt-panel { margin-top }` HERE, DELIBERATELY.
   The only place two panels are ever adjacent is inside .crt-side, which is a
   flex column with `gap: 16px` — so a sibling margin does not replace that
   spacing, it ADDS to it. Measured: 32px between the promo box and the totals
   box against 16px everywhere else on the page, which reads as the summary
   having drifted loose. Spacing between blocks belongs to the container that
   arranges them, exactly as it does to .dash-content on the panel pages. */
.crt-panel-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 6px 16px;
    padding: 20px 24px;
    border-bottom: 1px solid var(--crt-border);
}

.crt-panel-head h2 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    color: #FFFFFF;
}

/* The standing sentence about live pricing. See the comment on it in
   cart/index.blade.php: there is deliberately no per-line "this got cheaper"
   badge, because a cart line stores no price to compare against. */
.crt-panel-head p {
    margin: 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--crt-muted);
}

.crt-panel-body { padding: 20px 24px; }


/* ── One line ───────────────────────────────────────────────────────────────
   SIX CELLS AT FULL WIDTH, and the three numeric ones are fixed so that the
   prices in a five-line cart form a column the eye can add up. Only the item
   cell flexes.

   THE FIRST TRACK IS THE PRODUCT PICTURE, at the 56px the cart drawer has drawn
   it at since the drawer was built. A TRACK rather than an image inside the item
   cell: 56px is 56px whatever the product is called, where a flex child of the
   name cell would be squeezed by "Counter-Strike 2 External". .cdr-line is a
   grid for the identical reason, and this is that row's arrangement widened by
   the three numeric columns a page has room for and a 420px panel does not.

   WHAT IT COSTS THE ROW VERTICALLY: nothing. Measured at 1440 the shortest line
   on the page is 125px tall (name, plan pill, term and a 44px stepper), so a
   56px square fits inside a cell that already exists.

   WHAT IT COSTS HORIZONTALLY IS PAID FOR BY THE THREE NUMERIC COLUMNS, and that
   is the whole reason they changed. The line is 744px of content at 1440 (792
   pane, 24px of padding a side). Dropping a 56px track and a 16px gap in front
   of the item cell without touching anything else took it from 304px to 232 —
   and the product NAME still fitted, because the name is 20px on one line at
   both. What did not fit was the prose UNDER it: the "3 × 30 days = 90 days"
   sentence and CartProblem's renewal notices re-wrapped and the four lines of
   the measured basket went 217/172/152/125 → 246/201/181/134, +29px each and
   +320px on the document. A picture is not worth 320px.

   So the fixed columns were re-measured against what they actually hold instead
   of being left where they were. Every string was measured through a canvas at
   the exact computed font of the cell it renders in:

     unit  104 → 84   "€10,000.00" is 77.5px at 600 14px Outfit; the widest this
                      catalog can produce is €300.00 at 58.2. "each" sits under
                      it and is narrower still.
     qty   128 → 108  .crt-qty measures 104px (two 34px steps, a 34px value and
                      1px of border a side) and .crt-qty-fixed is 44.
     total 104 → 88   "€10,000.00" is 83px at 600 15px; the widest a line total
                      can reach here is 12 × €50 = €600.00 at 62.7.

   84 + 108 + 88 = 280, which is the 336 they used to take minus the 56 the
   picture needs. The fixed tracks therefore still add up to exactly 376px with
   the art track in front of them, the item cell settles at 288 against 304
   before, and nothing in it re-wraps. .crt-money is nowrap, so these are floors
   and not wrap points: they are set from the ceiling, not from today's catalog.

   Rows are separated by a border rather than a gap so a long cart reads as a
   list; the last one drops it because the panel already has an edge there. */
.crt-line {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) 84px 108px 88px 40px;
    grid-template-areas: "art item unit qty total remove";
    align-items: center;
    gap: 12px 16px;
    padding: 20px 24px;
    border-bottom: 1px solid var(--crt-border);
}

.crt-line:last-child { border-bottom: 0; }

/* An item that cannot be sold right now still renders — the customer has to be
   told WHICH one is the problem — but it is visibly stood down, and it
   contributes nothing to the subtotal (PricedCart does that arithmetic, not
   this file). The sentence beside it carries the reason; this only makes the
   line look like what the sentence says it is. */
.crt-line.is-blocked { background: rgba(239, 68, 68, .04); }

/* TOP-ALIGNED, ALONE AMONG THE SIX. The row is align-items:center because five
   short cells against one tall one look wrong any other way, but the picture
   belongs beside the product NAME, and the name is at the top of a cell that can
   run to 217px once a plan note and two problem sentences are under it. Centred,
   the tile drifts to the middle of that column and reads as belonging to
   nothing. The drawer aligns its own row to start for the same reason. */
.crt-cell-art    { grid-area: art; align-self: start; }

/* The shared well takes this page's palette; see .cart-art in enhancements.css
   for why the colours are bound at the call site rather than written into it. */
.crt-cell-art > .cart-art {
    --cart-art-border: var(--crt-border);
    --cart-art-bg:     var(--crt-raised);
}

.crt-cell-item   { grid-area: item; min-width: 0; }
.crt-cell-unit   { grid-area: unit; }
.crt-cell-qty    { grid-area: qty; }
.crt-cell-total  { grid-area: total; }
.crt-cell-remove { grid-area: remove; }

.crt-item-name {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.35;
    color: #FFFFFF;
    /* Wraps rather than truncates. A product name is the one thing on this row
       a customer must be able to read in full to know what they are buying, and
       there is no hover on a phone to reveal an ellipsis. */
    overflow-wrap: anywhere;
}

.crt-item-name a {
    color: inherit;
    text-decoration: none;
    transition: color .2s ease;
}

.crt-item-name a:hover { color: var(--crt-accent); }

.crt-item-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin-top: 6px;
    font-size: 13px;
    color: var(--crt-secondary);
}

.crt-plan-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border: 1px solid var(--crt-border);
    border-radius: 999px;
    background: var(--crt-raised);
    font-size: 12px;
    font-weight: 500;
    color: var(--crt-secondary);
    white-space: nowrap;
}

.crt-plan-pill > i { font-size: 13px; font-style: normal; }

/* "3 × 30 days = 90 days of access."

   THE MOST IMPORTANT SENTENCE ON THE PAGE. A quantity here does NOT mean two
   licences — an entitlement is one (customer, product) pair and there is
   nowhere for a second to live — it means more TIME on the one subscription.
   See Cart::MAX_QUANTITY_PER_LINE. A customer who reads "3" and expects three
   keys opens a ticket the moment their order grants one, so the arithmetic is
   spelled out rather than implied. */
.crt-item-grant {
    margin: 6px 0 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--crt-muted);
}

.crt-money {
    font-size: 14px;
    font-weight: 600;
    color: #FFFFFF;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.crt-money-note {
    display: block;
    margin-top: 3px;
    font-size: 11.5px;
    font-weight: 400;
    color: var(--crt-muted);
}

.crt-cell-total .crt-money { font-size: 15px; }


/* ── The stepper ────────────────────────────────────────────────────────────
   A REAL FORM WITH TWO SUBMIT BUTTONS, and no JavaScript anywhere near it.

   Both buttons are name="quantity" and only the one actually pressed is
   submitted, which is what lets a single form carry both instructions with no
   collision. The value each carries is an ABSOLUTE quantity — current minus
   one, current plus one — so a double-submitted press cannot compound the way
   a delta would. CartController::update says the same thing from the other
   side.

   It is a flex ROW, so `flex: 0 0 34px` on the buttons resolves along the
   horizontal axis. Worth stating: a basis dropped into a flex-direction:column
   container resolves VERTICALLY, which is how .adm-search's `flex: 1 1 320px`
   once produced a 320px-tall box around a 51px input. */
.crt-qty {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0;
    width: fit-content;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius-sm);
    background: var(--crt-raised);
    overflow: hidden;
}

.crt-step {
    flex: 0 0 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* THE HEIGHT IS THE FREE AXIS, SO IT IS THE ONE THAT GOES TO 44.

       The note that used to sit here said "40px, not 34px — the button is a
       touch target before it is a decoration", and then declared 38. Measured
       on a phone the pair came out 34x38, and 31x38 below 400px where the
       flex-basis is cut again: under 40 on BOTH axes, on the control a customer
       taps repeatedly while changing what they are about to buy.

       Width is genuinely spoken for — the note in the 400px block below budgets
       the row down to the pixel and the stepper is competing with the line
       total for a 288px row — but nothing competes for vertical space here, so
       the height is raised to the 44px guideline and the basis is left alone.
       That alone takes the target from 1292px² to 1496px² and makes the axis a
       thumb actually misses on the compliant one. */
    height: 44px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--crt-secondary);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: background-color .2s ease, color .2s ease;
}

.crt-step > i { font-style: normal; }

.crt-step:hover:not(:disabled) {
    background: rgba(255, 255, 255, .05);
    color: #FFFFFF;
}

/* DISABLED, NOT HIDDEN. At quantity 1 there is nothing below to step to (the
   remove button is the way to zero) and at the cap there is nothing above.
   Removing the button would make the control jump one size narrower and shift
   everything beside it; greying it keeps the geometry still and says why. */
.crt-step:disabled {
    color: #4A4646;
    cursor: not-allowed;
}

.crt-qty-value {
    flex: 0 0 auto;
    min-width: 34px;
    padding: 0 4px;
    text-align: center;
    font-size: 14px;
    font-weight: 600;
    color: #FFFFFF;
    font-variant-numeric: tabular-nums;
}

/* A lifetime plan is capped at one, so its stepper has nothing to do. Rendering
   two dead buttons around a permanent "1" looks like a broken control, so the
   template swaps in this instead — the same box, the same height, no promise of
   an action that cannot happen. */
.crt-qty-fixed {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius-sm);
    background: var(--crt-raised);
    font-size: 14px;
    font-weight: 600;
    color: var(--crt-secondary);
    font-variant-numeric: tabular-nums;
}


/* ── Remove ─────────────────────────────────────────────────────────────────
   Its own form (POST + _method=DELETE), because a removal is a write and a
   write is never a GET — a link version is fireable by a prefetcher and by any
   third-party <img>, and the symptom is a basket that empties itself. */
/* 44px because it is destructive AND small, which is the worst pair to be. It
   measured 36x36 — under the guideline on both axes — and it sits in its own
   cell at the end of the row rather than inside the stepper's width budget, so
   there is nothing here to trade against. The icon and the hover treatment are
   unchanged; only the box a finger aims at grows. */
.crt-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--crt-radius-sm);
    background: transparent;
    color: var(--crt-muted);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: color .2s ease, border-color .2s ease, background-color .2s ease;
}

.crt-remove > i { font-style: normal; }

.crt-remove:hover {
    color: var(--crt-danger);
    border-color: rgba(239, 68, 68, .35);
    background: rgba(239, 68, 68, .08);
}


/* ── A sentence about something being wrong ────────────────────────────────
   One CartProblem, rendered where it belongs: beside the line it names, or in
   the summary when it is about the whole basket. The wording is always the
   problem's own — never composed in a template — so the cart page, the checkout
   page and any future email say the same thing about the same situation.

   NEVER COLOUR ALONE. Every one of these carries an icon and a full sentence;
   the tint is the third signal, not the first. */
.crt-note {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 10px;
    padding: 9px 12px;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius-sm);
    background: var(--crt-raised);
    font-size: 13px;
    line-height: 1.55;
    color: var(--crt-secondary);
}

.crt-note > i {
    flex: 0 0 auto;
    margin-top: 1px;
    font-size: 15px;
    font-style: normal;
    color: var(--crt-muted);
}

/* min-width:0 on the text, again: a flex item's automatic minimum is
   min-content, and one long unbreakable word in a refusal is enough to widen
   the note past its panel. */
.crt-note > span { min-width: 0; overflow-wrap: anywhere; }

.crt-note-bad {
    border-color: rgba(239, 68, 68, .30);
    background: rgba(239, 68, 68, .07);
    color: #F7C9C9;
}

.crt-note-bad > i { color: var(--crt-danger); }

.crt-note-warn {
    border-color: rgba(249, 115, 22, .30);
    background: rgba(249, 115, 22, .07);
    color: #F5D3B4;
}

.crt-note-warn > i { color: var(--crt-warning); }

.crt-note-ok {
    border-color: rgba(34, 197, 94, .30);
    background: rgba(34, 197, 94, .07);
    color: #BFEBCF;
}

.crt-note-ok > i { color: var(--crt-success); }

.crt-note a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}


/* ── Promo ──────────────────────────────────────────────────────────────────
   ONE FIELD AND ONE BUTTON, and clearing the field is how a code comes off —
   PromoSession::remember treats an empty submission as a removal, so there is
   no second control to find.

   flex-wrap with a 160px basis on the input: the field keeps the row at full
   width and drops the button onto its own line rather than squeezing to
   nothing. This is a flex ROW, so 160px is a width. */
.crt-promo-form {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.crt-promo-input {
    flex: 1 1 160px;
    min-width: 0;
    height: 42px;
    padding: 0 14px;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius-sm);
    background: var(--crt-bg);
    color: #FFFFFF;

    /* 14px with a pointer, 16px on a phone. Under 16 iOS Safari zooms the page
       on focus and never zooms back, and this is the one text field on the
       cart — the last screen before checkout. The token, the measurements and
       why it is max() rather than a flat 16 are at the top of enhancements.css. */
    font-size: max(var(--field-font-floor, 0px), 14px);
    letter-spacing: .04em;
    text-transform: uppercase;
    transition: border-color .2s ease;
}

.crt-promo-input::placeholder {
    color: #5C5757;
    letter-spacing: normal;
    text-transform: none;
}

.crt-promo-input:focus {
    outline: none;
    border-color: rgba(234, 156, 34, .55);
}

.crt-promo-form .btn-secondary {
    flex: 0 0 auto;
    height: 42px;
}


/* ── Summary ────────────────────────────────────────────────────────────────
   The figures, in the order they are read: what the goods cost, what came off,
   what is owed. */
.crt-sums {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.crt-sum {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    font-size: 14px;
    color: var(--crt-secondary);
}

.crt-sum > span:last-child {
    font-weight: 600;
    color: #FFFFFF;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.crt-sum-off > span:last-child { color: var(--crt-success); }

.crt-sum-label {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}

.crt-code {
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--crt-raised);
    font-size: 12px;
    font-weight: 600;
    color: var(--crt-accent);
    letter-spacing: .04em;
    overflow-wrap: anywhere;
}

.crt-sum-total {
    margin-top: 4px;
    padding-top: 16px;
    border-top: 1px solid var(--crt-border);
    font-size: 15px;
    color: #FFFFFF;
}

.crt-sum-total > span:last-child { font-size: 22px; font-weight: 700; }


/* ── Checkout ───────────────────────────────────────────────────────────────
   The one amber control on the page, so there is never a question about which
   button finishes the job.

   width:100% on a .btn-primary from theme.css: that class is
   display:inline-flex with 8px/20px padding and no width, which is right in a
   navbar and wrong as the final action of a column. Only the box changes; the
   colour, radius and hover are theme.css's and stay that way. */
.crt-checkout {
    width: 100%;
    justify-content: center;
    height: 48px;
    margin-top: 18px;
    font-size: 15px;
    font-weight: 600;
}

/* Disabled while something blocks the sale. It stays VISIBLE and stays in
   place: hiding it would leave a customer looking for the button, and the
   sentences directly underneath are what tell them how to get it back. */
.crt-checkout:disabled {
    background: #3A3535;
    color: #8A8585;
    cursor: not-allowed;
}

.crt-checkout:disabled:hover { background: #3A3535; }

.crt-side-note {
    margin: 12px 0 0;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--crt-muted);
    text-align: center;
}


/* ── Below the lines ────────────────────────────────────────────────────────
   Keep shopping on the left, empty the cart on the right — opposite ends,
   because they are opposite intentions and a mis-click on the destructive one
   costs a rebuilt basket. */
.crt-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 16px;
}

.crt-foot form { margin: 0; }

/* min-height rather than height: on a phone .crt-foot stretches this to the
   full row (see the 620px block) and the label is one line, so the box was
   398x36 — wide enough to hit and 8px short on the axis that matters. A minimum
   raises the short side without stopping it growing if the label ever wraps. */
.crt-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    gap: 6px;
    padding: 8px 16px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: var(--crt-muted);
    font-size: 13.5px;
    font-weight: 500;
    cursor: pointer;
    transition: color .2s ease, border-color .2s ease;
}

.crt-clear > i { font-style: normal; }

.crt-clear:hover {
    color: var(--crt-danger);
    border-color: rgba(239, 68, 68, .3);
}


/* ── Empty ──────────────────────────────────────────────────────────────────
   THE COMMON STATE, AND IT HAS TO LOOK DELIBERATE. Most visits to /cart find
   nothing in it — a bookmark, a navbar click, a return after checkout — and a
   bare "Your cart is empty." on a black page reads as a page that failed. So it
   says what the cart is FOR and offers the one route that fixes it. */
.crt-empty {
    text-align: center;
    padding: 72px 32px;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius);
    background: var(--crt-surface);
}

.crt-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border: 1px solid var(--crt-border);
    border-radius: 50%;
    background: var(--crt-raised);
    color: var(--crt-muted);
    font-size: 30px;
    font-style: normal;
}

.crt-empty h2 {
    margin: 20px 0 10px;
    font-size: 21px;
    font-weight: 600;
    color: #FFFFFF;
}

.crt-empty p {
    max-width: 440px;
    margin: 0 auto 26px;
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--crt-muted);
}


/* ── The product page's inline answer ──────────────────────────────────────
   .crt-added is the ONE block in this file that renders somewhere else: it sits
   inside .pricing-card on /store/{slug} and carries the sentence the add-to-cart
   fetch came back with. Everything it needs is declared on itself (see the token
   block at the top) because there is no .crt-page above it.

   Hidden until Alpine has a sentence to put in it, and with scripting off it
   never gets one — the ordinary flash toast does the job instead. So there is no
   state in which this is an empty bordered box. */
.crt-added {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin-top: 14px;
    padding: 11px 14px;
    border: 1px solid var(--crt-border);
    border-radius: var(--crt-radius-sm);
    background: var(--crt-raised);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--crt-secondary);
}

.crt-added > i {
    flex: 0 0 auto;
    margin-top: 1px;
    font-size: 16px;
    font-style: normal;
}

.crt-added > span { min-width: 0; overflow-wrap: anywhere; }

.crt-added a {
    flex: 0 0 auto;
    margin-left: auto;
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    white-space: nowrap;
}

.crt-added-ok {
    border-color: rgba(34, 197, 94, .30);
    background: rgba(34, 197, 94, .07);
    color: #BFEBCF;
}

.crt-added-ok > i { color: var(--crt-success); }

.crt-added-bad {
    border-color: rgba(239, 68, 68, .30);
    background: rgba(239, 68, 68, .07);
    color: #F7C9C9;
}

.crt-added-bad > i { color: var(--crt-danger); }


/* ============================================================================
   RESPONSIVE
   ----------------------------------------------------------------------------
   Two restacks, at the two widths where the layout actually breaks rather than
   at round numbers borrowed from a framework:

     980px  the summary column stops fitting beside the lines
     680px  the five-cell line row stops fitting on one line
   ========================================================================== */

@media (max-width: 980px) {
    /* One column. The summary goes BELOW the lines, which is the reading order
       anyway — you check what is in the basket before you check what it costs —
       and it stops being sticky because it is now the last thing on the page and
       has nothing left to follow. */
    .crt-layout { grid-template-columns: minmax(0, 1fr); }

    .crt-side { position: static; top: auto; }
}

@media (max-width: 680px) {
    /* THE LINE BECOMES THREE ROWS.

       Squeezing five cells into 320px produces either a horizontal scrollbar or
       a 34px-wide product name, so it restacks instead: the name and the remove
       button on top, the unit price under it, and the stepper facing the line
       total at the bottom. Every number stays on the row it belongs to and
       nothing is dropped — this is a basket, and a cell hidden here is a figure
       the customer cannot check.

       The stepper is 106px and the total is right-aligned in the remaining
       track, so at 360px (288px of usable row) there is 180px of slack. */

    /* AND THE SLACK IS WHAT PAYS FOR THIS. Once the line restacks, the stepper
       has a whole grid track to itself — measured at 360x800 the qty column is
       235.4px wide and .crt-qty (width:fit-content) occupies 92 of it, leaving
       143px unused. The buttons were 31x44: the height had already been raised
       to the guideline because "nothing competes for vertical space here", and
       the width was left at a basis that was cut TWICE on the way down, to 34
       and then to 31, against a row budget that this stacked layout no longer
       has. 44px each takes .crt-qty to 118 and leaves 117px of the track still
       empty.

       Stated here rather than in the 400px block below so that every width at
       which the line is stacked gets the same control; the block below then
       only has to stop cutting it back. */
    .crt-step { flex-basis: 44px; }

    /* THE PICTURE STAYS INLINE WITH THE NAME. IT IS THE ONE THING THAT DOES NOT
       STACK, and that is the whole reason it is worth having at 360px: a
       thumbnail under the product name is a 56px band of decoration, while a
       thumbnail BESIDE it is what lets somebody scanning a four-line basket on a
       phone find the row they meant without reading. It is also exactly what the
       drawer does at this width — the drawer becomes a bottom sheet below 560px
       and keeps its 56px art column throughout — so the page and the panel show
       the same basket the same way on the same phone.

       WHAT STACKS INSTEAD is everything that is a figure or a control: the unit
       price with the remove button, then the stepper facing the line total. Both
       of those rows now start at the LEFT EDGE rather than under the picture,
       which is why art spans only the first row: a stepper indented 68px to
       clear a thumbnail two rows above it has 68px less to live in for nothing.

       The measure the name gets back: 288px of usable row at 360 (theme.css
       gives the container 20px a side, the line 14px more) minus a 56px track
       and its 12px gap leaves 220px, which holds "Counter-Strike 2 External" on
       two lines. */
    .crt-line {
        grid-template-columns: 56px minmax(0, 1fr) auto;
        grid-template-areas:
            "art  item item"
            "unit unit remove"
            "qty  qty  total";
        align-items: center;
        gap: 12px;
        padding: 18px 16px;
    }

    .crt-cell-unit  { align-self: center; }
    .crt-cell-qty   { justify-self: start; }
    .crt-cell-total { justify-self: end; text-align: right; }

    /* The remove button moves onto the price row rather than the title row: on
       the title row it would sit beside a name that wraps to three lines and
       drift to the vertical middle of it, which reads as belonging to nothing. */
    .crt-cell-remove { justify-self: end; }

    .crt-panel-head { padding: 16px; }
    .crt-panel-body { padding: 16px; }

    .crt-empty { padding: 56px 20px; }
    .crt-empty p { font-size: 14px; }

    /* Both full width, stacked, keep-shopping first. Side by side at this width
       the two buttons are 150px each with 8px between them and the destructive
       one is a thumb-width from the safe one. */
    .crt-foot {
        flex-direction: column;
        align-items: stretch;
    }

    .crt-foot > * { width: 100%; }
    .crt-foot .btn-secondary { justify-content: center; }
    .crt-clear { justify-content: center; width: 100%; }
}

@media (max-width: 400px) {
    /* 360px is the narrowest phone anybody still ships. The container is 320px
       here (theme.css:40 gives it 20px of side padding), the line's own padding
       takes 32px more, and 288px is what a row has to live in. */
    .crt-page { padding-bottom: 72px; }

    .crt-line { padding: 16px 14px; }
    .crt-item-name { font-size: 14.5px; }

    /* The stepper does NOT lose 6px per button here any more. This block used
       to cut the basis to 31px "which leaves the line total 180px of the row to
       sit in" — but by 400px the line has already restacked (the 680px block
       above), the stepper and the total are on their own row, and the total is
       right-aligned in a second track that the stepper never reaches. Measured
       at 360x800 with the cut in place: buttons 31x44, qty column 235.4px wide,
       .crt-qty 92px, 143px of the track unused. The cut bought nothing and cost
       13px on the short axis of the control a customer taps most on this page.

       The value cell keeps its narrower 28px: that is text, not a target, and
       three digits still fit. */
    .crt-qty-value { min-width: 28px; }
}
