/* Cart, checkout and order. Loaded after tokens.css and base.css.
   Every colour comes from a token — no hex below this line. */

.page{max-width:1120px;margin:0 auto;padding:118px var(--pad) 90px}
.page__h{font-size:clamp(30px,4vw,42px);margin-bottom:8px}
.page__sub{color:var(--silver);font-size:15.5px;line-height:1.6;margin-bottom:34px}

.cols2{display:grid;grid-template-columns:1.55fr 1fr;gap:44px;align-items:start}
@media(max-width:900px){.cols2{grid-template-columns:1fr;gap:32px}}

/* ============ NOTICES ============
   Not live regions. The banner is rendered at boot, and content present at
   first render is never announced anyway; a live region here would only
   collide with the browser's own page-load announcement. It is discoverable
   because it precedes the h1, it is named in the title, and it is the
   aria-describedby of the button it blocks. */
.note{border-radius:var(--r-md);padding:18px 22px;margin-bottom:26px;border-left:4px solid var(--line)}
.note[hidden]{display:none}
.note__h{font-size:17px;font-weight:600;margin-bottom:6px}
.note p{font-size:14.5px;line-height:1.6;color:var(--silver)}
.note--warn{background:var(--mist);border-left-color:var(--red)}
.note--warn .note__h{color:var(--ink)}
.note a{text-decoration:underline}

/* Error summary. Focus is what announces it, so it is NOT role=alert — being
   both focused and live means the screen reader reads it twice. */
.formerr{border-radius:var(--r-md);padding:20px 24px;margin-bottom:26px;
  background:var(--red-bg);border-left:4px solid var(--red-ink)}
.formerr[hidden]{display:none}
.formerr__h{font-size:18px;font-weight:600;margin-bottom:6px}
.formerr p{font-size:14.5px;color:var(--ink);margin-bottom:10px}
.formerr ul{list-style:none;display:flex;flex-direction:column;gap:7px}
.formerr li a{color:var(--red-ink);text-decoration:underline;font-size:14.5px;font-weight:600}

/* ============ QUANTITY ============
   --ctrl-line, not --line: this is the visible boundary of an active control,
   and --line is 1.26:1 on white. Buttons carry no border of their own — the
   group border is the boundary and two would double-line. */
.qty{display:inline-flex;align-items:center;gap:2px;flex:none;
  border:1.5px solid var(--ctrl-line);border-radius:var(--pill);padding:3px}
.qty button{width:34px;height:34px;border-radius:var(--pill);display:grid;place-items:center;
  font-size:17px;line-height:1}
.qty button:hover{background:var(--mist)}
/* aria-disabled, never disabled — the reason has to stay reachable. And
   therefore no opacity: a focusable control still has to meet contrast. */
.qty button[aria-disabled="true"]{color:var(--silver);cursor:not-allowed}
.qty button[aria-disabled="true"]:hover{background:none}
.qty input{width:46px;min-height:34px;text-align:center;border:0;background:none;
  font-family:'JetBrains Mono',monospace;font-size:15px;
  -moz-appearance:textfield;appearance:textfield}
.qty input::-webkit-outer-spin-button,
.qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* ============ CART LINES ============ */
.clines{list-style:none;display:flex;flex-direction:column;gap:2px}
.cline{display:grid;grid-template-columns:78px 1fr auto;gap:18px;align-items:center;
  padding:20px 0;border-bottom:1px solid var(--line)}
.cline__img{background:var(--mist);border-radius:var(--r-sm);padding:9px}
.cline__img svg{width:100%;height:auto}
.cline__t b{font-family:'Outfit',sans-serif;font-size:16.5px;font-weight:600;display:block;margin-bottom:4px}
.cline__t span{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--silver);line-height:1.5}
.cline__right{display:flex;align-items:center;gap:20px}
.cline__money{font-family:'Outfit',sans-serif;font-size:17px;font-weight:600;min-width:88px;text-align:right}

/* Status is never colour alone — the words carry it, the left rule is a second
   channel, and the glyph is aria-hidden. Deliberately NOT opacity dimming: the
   .pcard.nofit pattern drops its own text to 2.79:1. */
.cline__status{grid-column:2/-1;font-size:13.5px;font-weight:600;margin-top:8px;
  display:flex;align-items:center;gap:7px}
.cline__status--stop{color:var(--red-ink)}
.cline__status--warn{color:var(--warn)}
.cline--problem{border-left:3px solid var(--red-ink);padding-left:13px}
.cline--warn{border-left:3px solid var(--warn);padding-left:13px}

@media(max-width:620px){
  /* Reflow to 320px without display:block, which would destroy the semantics. */
  .cline{grid-template-columns:64px 1fr;gap:14px}
  .cline__right{grid-column:1/-1;justify-content:space-between}
}

.cline__rm{font-size:13px;color:var(--silver);text-decoration:underline}
.cline__rm:hover{color:var(--red)}

.cart-empty{padding:60px 0;text-align:center}
.cart-empty h2{font-size:24px;margin-bottom:10px}
.cart-empty p{color:var(--silver);margin-bottom:24px}

/* ============ TOTALS ============
   Not live regions: on one settle the line prices, subtotal, shipping, tax,
   total and shipping sentence all change in the same tick, and marking any of
   them live means the reader picks one and drops the rest. The composed
   announcement carries the numbers. */
.totals{background:var(--mist);border-radius:var(--r-lg);padding:28px;position:sticky;top:96px}
.totals h2{font-size:19px;margin-bottom:18px}
.totals dl{display:grid;grid-template-columns:1fr auto;gap:11px 16px;margin-bottom:16px}
.totals dt{font-size:14.5px;color:var(--silver)}
.totals dd{font-size:14.5px;font-weight:600;text-align:right}
.totals__grand{display:flex;justify-content:space-between;align-items:baseline;
  padding-top:16px;border-top:1px solid var(--line);margin-bottom:20px}
.totals__grand span{font-size:15px;font-weight:600}
.totals__grand b{font-family:'Outfit',sans-serif;font-size:26px;font-weight:600}
/* Progress bar is decorative and aria-hidden: its accessible value would be a
   percentage of an unnamed total, while #shipTxt already states the actionable
   fact in dollars. Fill vs track is 4.94:1, which is what 1.4.11 asks of a
   meter — the track-vs-page edge conveys nothing the sentence does not. */
.ship{margin-bottom:18px}
.ship p{font-size:13px;font-weight:600;margin-bottom:9px}
.ship.is-free p{color:var(--go-ink)}
.ship__bar{height:8px;border-radius:var(--pill);background:var(--cloud);overflow:hidden;
  box-shadow:inset 0 0 0 1px var(--line)}
.ship__fill{height:100%;width:var(--pct,0%);background:var(--go-ink);border-radius:var(--pill);
  transition:width .4s var(--ease)}
@media(forced-colors:active){
  .ship__bar{background:Canvas;border:1px solid CanvasText;box-shadow:none}
  .ship__fill{background:Highlight}
}

/* ============ SUMMARY TABLE ============
   A table, not a dl: tfoot + th[scope=row] expresses that the totals summarise
   the rows above, which a dl cannot. Two columns so it reflows to 320px
   without display:block, which would destroy the table semantics. */
.summary{width:100%;border-collapse:collapse}
.summary th,.summary td{text-align:left;padding:13px 0;border-bottom:1px solid var(--line);
  font-size:14.5px;vertical-align:top}
.summary td{text-align:right;white-space:nowrap;font-weight:600}
.summary thead th{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--silver);font-weight:500}
.summary tbody th{font-weight:600;font-family:'Outfit',sans-serif;font-size:15px;padding-right:16px}
.summary__opt,.summary__qty{display:block;font-family:'JetBrains Mono',monospace;
  font-size:11.5px;color:var(--silver);font-weight:400;margin-top:3px}
.summary tfoot th{font-weight:500;color:var(--silver);font-size:14.5px}
.summary tfoot .summary__total th,
.summary tfoot .summary__total td{font-family:'Outfit',sans-serif;font-size:19px;font-weight:600;
  color:var(--ink);border-bottom:0;padding-top:16px}

/* ============ FORM ============ */
.fset{border:0;padding:0;margin:0 0 32px}
.fset__legend{font-family:'Outfit',sans-serif;font-size:20px;font-weight:600;margin-bottom:16px;padding:0}
.frow{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:600px){.frow{grid-template-columns:1fr}}
.field2{display:flex;flex-direction:column;gap:7px;margin-bottom:16px}
.field2 label{font-size:13.5px;font-weight:600}
.field2 .opt-tag{color:var(--silver);font-weight:400}
/* min-height not height, so the box grows under WCAG 1.4.12 text spacing.
   16px font — under that, iOS Safari zooms the viewport on focus and breaks
   reflow on a form that cannot afford it. --ctrl-line for the boundary. */
.field2 input,.field2 select{min-height:52px;padding:12px 16px;border-radius:var(--r-sm);
  border:1.5px solid var(--ctrl-line);background:var(--paper);font-size:16px;width:100%}
.field2 input:focus,.field2 select:focus{border-color:var(--graphite)}
.field2 input:focus:not(:focus-visible),
.field2 select:focus:not(:focus-visible){outline:none}
/* Border WIDTH changes too — invalid must not be signalled by hue alone. */
.field2 input[aria-invalid="true"],.field2 select[aria-invalid="true"]{
  border-color:var(--red-ink);border-width:2px}
/* Starts empty. A node referenced by aria-describedby is read even when
   hidden, so pre-filled text would be appended to the field on every focus. */
.fielderr{color:var(--red-ink);font-size:13px;font-weight:600}
.fielderr:empty{display:none}
.hint{color:var(--silver);font-size:13px}

/* ============ FORCED COLORS ============
   Tints, gradients and shadows are all discarded in Windows contrast themes,
   which would collapse every status into identical plain text. The words
   already distinguish them; these rules restore the boundaries. */
@media(forced-colors:active){
  .qty,.field2 input,.field2 select{border-color:CanvasText}
  .field2 input[aria-invalid="true"],
  .field2 select[aria-invalid="true"]{border-color:CanvasText;border-style:dashed}
  .cline--problem,.cline--warn{border-left-color:CanvasText;border-left-style:dashed}
  .cline__img{background:Canvas;border:1px solid CanvasText}
  .status{border:1px solid CanvasText;background:Canvas;color:CanvasText}
  .status--cancelled,.status--refunded{border-style:dashed}
  .note,.formerr{border:1px solid CanvasText}
}

/* ============ RECEIPT ============ */
.receipt__meta{display:flex;flex-wrap:wrap;gap:10px 26px;margin-bottom:30px}
.receipt__meta div{display:flex;flex-direction:column;gap:3px}
.receipt__meta span{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--silver)}
.receipt__meta b{font-family:'Outfit',sans-serif;font-size:16px;font-weight:600}
.status{display:inline-flex;align-items:center;gap:7px;padding:5px 13px;border-radius:var(--pill);
  font-size:12.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
/* The status WORD is inside the badge, so the tint is a third channel, not the
   signal. Text ratios: pending 5.39, paid 5.21, shipped 14.71, cancelled 5.10. */
.status--pending{background:var(--warn-bg);color:var(--warn)}
.status--paid,.status--delivered{background:var(--go-bg);color:var(--go-ink)}
.status--shipped{background:var(--cloud);color:var(--graphite)}
.status--cancelled,.status--refunded{background:var(--red-bg);color:var(--red-ink)}
.addr{font-size:14.5px;line-height:1.7;color:var(--silver)}
.addr b{color:var(--ink);display:block;font-weight:600}

/* ============ CONTENT PAGES ============
   Legal, policy and support. Measure is capped near 70 characters because
   these are the only pages on the site people actually read at length. */
.page--doc{max-width:760px}
.page--doc h2{font-family:'Outfit',sans-serif;font-size:23px;font-weight:600;
  margin:38px 0 12px;line-height:1.25}
.page--doc h3{font-family:'Outfit',sans-serif;font-size:18px;font-weight:600;margin:26px 0 10px}
.page--doc p{font-size:16px;line-height:1.7;margin-bottom:14px;max-width:70ch}
.page--doc a{text-decoration:underline;text-underline-offset:3px}
.page--doc code{font-family:'JetBrains Mono',monospace;font-size:13.5px;
  background:var(--mist);padding:2px 6px;border-radius:6px}

.plist{list-style:none;display:flex;flex-direction:column;gap:10px;margin-bottom:16px;max-width:70ch}
.plist li{position:relative;padding-left:20px;font-size:16px;line-height:1.7}
.plist li::before{content:"";position:absolute;left:2px;top:11px;width:6px;height:6px;
  border-radius:var(--pill);background:var(--red)}

/* Policy tables carry real relationships — a term, why it exists, how long it
   lasts — so they stay tables rather than becoming stacked divs at narrow
   widths, which would destroy the header association. */
.ptable{width:100%;border-collapse:collapse;margin:8px 0 20px;font-size:15px}
.ptable th,.ptable td{text-align:left;vertical-align:top;padding:12px 14px 12px 0;
  border-bottom:1px solid var(--line);line-height:1.6}
.ptable thead th{font-family:'JetBrains Mono',monospace;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--silver);font-weight:500}
.ptable tbody th{font-weight:600;padding-right:20px;min-width:9rem}

.faq{border-bottom:1px solid var(--line)}
.faq summary{cursor:pointer;padding:18px 0;list-style:none;display:flex;
  align-items:center;justify-content:space-between;gap:16px}
.faq summary::-webkit-details-marker{display:none}
.faq summary h2{font-size:17.5px;margin:0;font-weight:600}
.faq summary::after{content:"+";font-size:22px;color:var(--silver);flex:none;line-height:1}
.faq[open] summary::after{content:"\2212"}
.faq summary:hover h2{color:var(--red-ink)}
.faq p{padding-bottom:20px;color:var(--silver);max-width:70ch}

.doc-nav{margin-top:56px;padding-top:28px;border-top:1px solid var(--line)}
.doc-nav h2{font-size:15px;margin:0 0 14px}
.doc-nav ul{list-style:none;display:flex;flex-wrap:wrap;gap:10px}
.doc-nav a{display:inline-block;padding:8px 16px;border-radius:var(--pill);
  border:1px solid var(--line);font-size:14px;text-decoration:none}
.doc-nav a:hover{border-color:var(--graphite)}


/* ============ NOVA POSHTA PICKER ============
   Every colour here is a token. The list sits over the field below it, so it
   needs a solid background of its own — a transparent one would let the next
   label show through the options. */
.field2 { position: relative; }

.ac {
  position: absolute;
  z-index: 30;
  left: 0; right: 0;
  margin: 4px 0 0;
  padding: 4px;
  list-style: none;
  max-height: 280px;
  overflow-y: auto;
  background: var(--paper);
  border: 1px solid var(--ctrl-line);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgba(23, 26, 32, .14);
}

.ac__opt {
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: 14.5px;
  line-height: 1.4;
  cursor: pointer;
}

/* aria-selected is the state a screen reader reads, so it is also the state
   the highlight is drawn from — one source of truth, and they cannot drift. */
.ac__opt:hover,
.ac__opt[aria-selected="true"] {
  background: var(--mist);
}

/* ============ PAYMENT METHOD ============ */
.paylist { display: grid; gap: 10px; }

.payopt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--ctrl-line);
  border-radius: var(--r-md);
  font-size: 15px;
  cursor: pointer;
}

/* :has, not a JS-applied class — the checked state is already in the DOM and
   duplicating it in a class is one more thing to get out of step. */
.payopt:has(input:checked) {
  border-color: var(--ink);
  background: var(--mist);
}
