/* perennial — 購物車 · 結帳 · 我的帳戶

   The only stylesheet in this theme that styles markup the theme did not
   write. The cart and the checkout are WooCommerce blocks: they build
   themselves in the browser from the Store API, there is no PHP template to
   override, and 綠界 ECPay's eleven gateways and its 發票開立 / 載具類型 fields
   all arrive inside that block. So the blocks stay, and this is type, colour
   and rules laid over them. 我的帳戶 is the other kind — the classic
   `[woocommerce_my_account]` shortcode — and gets the same treatment at the
   bottom of the file.

   The grammar is 政策條款's, because these pages are the same kind of thing: a
   record, not a story. A record is a list of separate parts, and what
   separates them is a hairline and nothing else. Everything this file does to
   WooCommerce's defaults follows from that:

     · boxes become rules. The checkout ships as a stack of bordered cards
       with rounded corners; each step is now a hairline above it, the way a
       policy's sections are. Same for every payment method and shipping rate,
       which shipped as rounded highlighted boxes.
     · one type scale. Round 22 settled on three sizes, and the blocks arrive
       with their own em-based scale on top of a 22px --wp--preset--font-size
       --medium. That variable is redefined for this scope rather than fought
       rule by rule — it is the one custom property WooCommerce's stylesheet
       reads that we can reach.
     · the theme's ink and paper. WooCommerce's blue (#0675c4 focus ring,
       #1e1e1e text) is replaced everywhere it lands.
     · buttons are .pn-btn. There is one button shape on this site.

   Specificity: this sheet loads after WooCommerce's three block stylesheets
   and after Blocksy's woocommerce-cart-checkout-blocks bundle, so an equal
   weight wins on order. Where a rule below carries more than it looks like it
   needs, the weight it is beating is named in a comment. */

/* ── The frame ────────────────────────────────────────────────────────── */

.pn-commerce .pn-page {
	/* WooCommerce's blocks size everything off this. 22px by default, which
	   is between our 16 and our h3 and belongs to neither. */
	--wp--preset--font-size--medium: var(--pn-text-h3);
	--wp--preset--font-size--small: var(--text-small);
	--wc-separator-color: var(--line-hair);
}

/* No seam between the name of the page and the page. An earlier build ruled
   under it, on the argument that below the rule everything is a form — but the
   first thing under it, 聯絡資訊, is a heading with its own rule above it, so
   the two landed a few pixels apart and read as a double line. The 48px of air
   `.pn-page__head` already carries on every other page separates them, and a
   rule that close to another one is decoration. */

/* WooCommerce's own width, and Blocksy's, both go: the page is already inside
   .pn-container, which is the theme's measure. `alignwide` would add a second
   one and the two do not agree. */
.pn-commerce .pn-page__body > .alignwide,
.pn-commerce .wc-block-components-sidebar-layout {
	width: 100%;
	max-width: none;
	margin-inline: 0;
}

/* ── Type and colour, over the blocks ─────────────────────────────────── */

.pn-commerce :is(.wc-block-components-main, .wc-block-components-sidebar, .woocommerce) {
	font-family: var(--font-sans);
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-primary);
}

/* Nothing in a record is rounded and nothing floats. The blocks ship as
   stacks of rounded, shadowed cards, and taking the corners off one selector
   at a time would be a list with no end to it.

   This lands at 0-2-1 because of the element in the `:is()`, which is more
   than most of the rules below carry — so anything that is *meant* to be
   round has to say so at 0-2-1 or better. There is exactly one: the quantity
   badge in 訂單摘要, which is a counter and a counter is a circle. It was
   square until this was measured. The fields and the radio keep their own
   geometry because neither `input` nor `svg` is in this list. */
.pn-commerce .pn-page__body :is(div, section, fieldset, table, tr, td, th, p, span, a, button, h2, h3, h4) {
	border-radius: 0;
	box-shadow: none;
}

/* Every heading the blocks draw — 訂單摘要, 購物車總計, and each step's name.
   `.wc-block-components-title.wc-block-components-title` is WooCommerce's own
   0-2-0 doubled selector, so this carries the scope to land at 0-3-0. */
.pn-commerce .wc-block-components-title.wc-block-components-title,
.pn-commerce .wc-block-cart__totals-title,
.pn-commerce .wc-block-components-checkout-order-summary__title-text,
.pn-commerce .wc-block-components-checkout-step__title {
	margin: 0;
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-medium);
	color: var(--text-primary);
	text-transform: none;
}

/* 購物車總計 ships uppercased and tracked, which is the label register, and
   this is a heading. */
.pn-commerce .wc-block-cart__totals-title {
	padding-bottom: var(--space-4);
	letter-spacing: var(--ls-h3);
}

/* The line under a step's name that says what the step wants. */
.pn-commerce .wc-block-components-checkout-step__description,
.pn-commerce .wc-block-components-checkout-step__heading-content {
	margin-top: var(--space-2);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

.pn-commerce :is(.wc-block-components-button.is-link, .wc-block-components-address-card__edit, .woocommerce a) {
	color: var(--text-primary);
	text-decoration: none;
	transition: opacity var(--dur-fast) var(--ease-out);
}
.pn-commerce :is(.wc-block-components-button.is-link, .wc-block-components-address-card__edit, .woocommerce a):hover {
	opacity: var(--hover-opacity);
}

/* WooCommerce's focus ring is a 2px #0675c4 with a white inset. Ours is the
   token, everywhere, and it has to out-weigh
   `.wc-block-components-button:not(.is-link):focus` — 0-3-0 with the
   pseudo-class. */
.pn-commerce .pn-page__body :is(a, button, input, select, textarea):focus {
	outline: none;
	box-shadow: none;
}
.pn-commerce .pn-page__body :is(a, button, input, select, textarea):focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}

/* ── The steps: rules, not cards ──────────────────────────────────────── */

.pn-commerce .wc-block-components-checkout-step {
	margin: 0;
	padding: var(--space-6) 0;
	background: transparent;
	border: 0;
	border-top: var(--border-hair);
}

/* The first step opens the page, so nothing rules above it.

   `:first-child` alone does not find it. WooCommerce's checkout form opens
   with an empty, class-less <div> — the slot the express-payment buttons would
   render into, measured at 0px high with none configured — so 聯絡資訊 is the
   *second* child and kept a rule that ran between it and the page title. The
   contact-information block is always the first step WooCommerce renders, so
   it is named outright; the two selectors below it stay for the day a slot
   before it does render something. */
.pn-commerce .wc-block-checkout__form > .wc-block-checkout__contact-fields,
.pn-commerce .wc-block-checkout__form > *:first-child .wc-block-components-checkout-step,
.pn-commerce .wc-block-checkout__form > .wc-block-components-checkout-step:first-child {
	border-top: 0;
	padding-top: 0;
}

.pn-commerce .wc-block-components-checkout-step__heading {
	margin: 0 0 var(--space-5);
	padding: 0;
}

.pn-commerce .wc-block-components-checkout-step__content {
	padding: 0;
}

/* ── Buttons: one shape ───────────────────────────────────────────────── */

/* `wp-element-button` is styled by theme.json and by Blocksy's bundle, and
   `.wc-block-components-button:not(.is-link)` is 0-3-0 — hence the scope plus
   the same negation here. */
.pn-commerce .pn-page__body .wc-block-components-button:not(.is-link),
.pn-commerce .pn-page__body :is(.wp-element-button, .woocommerce-button, .button, button[type="submit"]):not(.is-link) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	min-height: 44px;
	height: auto;
	padding: var(--space-3) var(--space-5);
	background: var(--bg-brand);
	color: var(--text-on-brand);
	border: var(--line-weight) solid var(--bg-brand);
	border-radius: var(--radius-none);
	font-family: var(--font-sans);
	font-size: var(--text-small);
	font-weight: var(--weight-medium);
	line-height: 1.2;
	letter-spacing: 0;
	text-align: center;
	text-decoration: none;
	text-transform: none;
	box-shadow: none;
	transition: opacity var(--dur-fast) var(--ease-out);
}

.pn-commerce .pn-page__body .wc-block-components-button:not(.is-link):hover,
.pn-commerce .pn-page__body :is(.wp-element-button, .woocommerce-button, .button, button[type="submit"]):not(.is-link):hover {
	background: var(--bg-brand);
	border-color: var(--bg-brand);
	color: var(--text-on-brand);
	opacity: var(--hover-opacity);
	transform: none;
}

.pn-commerce .wc-block-components-button__text,
.pn-commerce .wc-block-components-checkout-place-order-button__text {
	display: inline-block;
	font-size: inherit;
	font-weight: inherit;
}

/* 前往結帳 and 下單購買 are the end of their column, so they take its width.
   Everything else is a button the size of its word. */
.pn-commerce .wc-block-cart__submit-button,
.pn-commerce .wc-block-components-checkout-place-order-button {
	width: 100%;
}

/* ── Fields ─────────────────────────────────────────────────────────────
   WooCommerce floats the label into the field: it sits centred over an empty
   box and shrinks into the top corner once something is typed, with
   `transform: scale(.82)` off 16px — which lands on 13.1px, a fourth size on
   a site that settled on three in Round 22. The first build of this sheet
   kept the mechanism and restyled it; measured, the label at 16px overlapped
   the value in every select, because a select always has a value and their
   shrink only fires on `.is-active`.

   So the label goes above the field, which is what every other form this
   theme has built already does — 合作's three applications, the contact
   record. No JavaScript is needed for it either way: a text field is <input>
   then <label>, so its wrapper is column-reverse; a select is <label> then
   <select>, so the label only has to stop being absolute. WooCommerce goes on
   toggling `.is-active` and it now means nothing. ─────────────────────────── */

.pn-commerce .wc-block-components-text-input {
	display: flex;
	flex-direction: column-reverse;
}

.pn-commerce .wc-blocks-components-select__container {
	position: relative;
}

.pn-commerce .wc-block-components-text-input label,
.pn-commerce .wc-blocks-components-select__label {
	position: static;
	transform: none;
	max-width: none;
	margin: 0 0 var(--space-2);
	padding: 0;
	overflow: visible;
	font-family: var(--font-sans);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	color: var(--text-secondary);
	white-space: normal;
}

.pn-commerce .pn-page__body :is(input[type="text"], input[type="email"], input[type="tel"], input[type="number"], input[type="password"], input[type="search"], select, textarea) {
	width: 100%;
	min-height: 44px;
	padding: 0 var(--space-4);
	background: var(--bg-page);
	color: var(--text-primary);
	border: var(--line-weight) solid var(--line-hair);
	border-radius: var(--radius-sm);
	font-family: var(--font-sans);
	font-size: var(--text-body);
	line-height: 1.4;
	box-shadow: none;
	-webkit-appearance: none;
	appearance: none;
}

.pn-commerce .pn-page__body textarea {
	padding: var(--space-3) var(--space-4);
}

.pn-commerce .pn-page__body :is(input, select, textarea):focus-visible {
	border-color: var(--line-strong);
}

/* The select's caret was positioned against a container that was the field;
   the label above it has made the container taller, so it is measured off the
   bottom now — (44 - 24) / 2. */
.pn-commerce .wc-blocks-components-select__expand {
	top: auto;
	bottom: 10px;
	right: var(--space-4);
	transform: none;
	fill: var(--text-secondary);
}

.pn-commerce .wc-block-components-validation-error {
	margin-top: var(--space-2);
	font-size: var(--text-caption);
	line-height: var(--lh-caption);
	color: var(--error);
}

.pn-commerce .pn-page__body :is(input, select, textarea)[aria-invalid="true"] {
	border-color: var(--error);
}

/* ── 發票開立 and 載具類型 ─────────────────────────────────────────────
   綠界's two invoice fields are not WooCommerce form controls at all: they are
   @wordpress/components SelectControls, so the <select> sits in an
   `.components-input-control__container` with an emotion-styled <div> drawing
   the border behind it and a <span> drawing the chevron. None of the rules
   above reach any of that, and the container drew a second border around a
   field that already had ours.

   They are the fields a Taiwanese buyer has to get right for the invoice to
   be issued to the right place, so they get the same shape as the rest. ──── */

.pn-commerce .components-base-control__label,
.pn-commerce .components-input-control__label {
	display: block;
	margin: 0 0 var(--space-2);
	font-family: var(--font-sans);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	letter-spacing: 0;
	color: var(--text-secondary);
	text-transform: none;
}

.pn-commerce .components-input-control__container {
	position: relative;
	width: 100%;
}

/* The border is the select's own, above. */
.pn-commerce .components-input-control__backdrop {
	display: none;
}

.pn-commerce .components-input-control__suffix {
	position: absolute;
	top: 50%;
	right: var(--space-4);
	transform: translateY(-50%);
	pointer-events: none;
	color: var(--text-secondary);
}

.pn-commerce .components-select-control__input {
	padding-right: var(--space-8);
}

/* ── Choosing one of several: shipping, payment ───────────────────────── */

/* The default is a rounded, bordered, tinted box per option, and a second
   border around the checked one. A row and a hairline say the same thing. */
.pn-commerce .wc-block-components-radio-control {
	border: 0;
}

/* The left padding is not spacing: WooCommerce positions the radio
   absolutely and relies on the option's own padding to make room for it.
   Taking the padding off with the box put a 20px circle on top of the first
   character of every payment method — 銀●轉帳, 貨○付款. The circle is pulled
   to the option's edge and the text clears it by 32px. */
.pn-commerce .wc-block-components-radio-control__option {
	margin: 0;
	padding: var(--space-4) 0 var(--space-4) var(--space-6);
	background: transparent;
	border: 0;
	border-top: var(--border-hair);
	border-radius: 0;
}

.pn-commerce .wc-block-components-radio-control__input {
	left: 0;
}

.pn-commerce .wc-block-components-radio-control > .wc-block-components-radio-control__option:first-child,
.pn-commerce .wc-block-components-radio-control-accordion-option:first-child .wc-block-components-radio-control__option {
	border-top: 0;
}

/* WooCommerce draws the hairline between two options with ::after, at 0-2-0
   with the element. Ours is the border-top above. */
.pn-commerce .wc-block-components-radio-control__option::after,
.pn-commerce .wc-block-components-radio-control-accordion-option::after {
	content: none;
}

/* Two more boxes, both belonging to the `--highlight-checked` variant, and
   neither of them reached by anything above.

   The first is a 4px-rounded 1px border around the *whole* group, drawn on the
   control's own ::after and inset to left:0 — which is exactly where the radio
   circle sits, because the circle is positioned absolutely at the option's
   left edge. Measured on 運送選項 at 1352px: the group's ::after box and the
   20px circle both start at x=64, so the circle straddles the line. That is
   what made it look broken; it was never the circle that was misplaced.

   The second is the ring around whichever option is chosen —
   `box-shadow: inset 0 0 0 1.5px currentColor` plus the same 4px radius. On
   付款選項 it was already gone, because each option there is a <div> and the
   de-rounding rule at the top of this file lists `div`. On 運送選項 each option
   is a <label>, which that list does not name, so 標準運費 kept a 1.5px ink box
   around it while every payment method had none.

   Both go. A row and a hairline already say which options belong together, and
   the filled circle already says which one is chosen. 0-3-1 and 0-3-0, over
   WooCommerce's 0-1-1 and 0-2-0. */
.pn-commerce .pn-page__body .wc-block-components-radio-control--highlight-checked::after {
	content: none;
}
.pn-commerce .wc-block-components-radio-control--highlight-checked :is(label, div)[class*="--checked-option-highlighted"] {
	border-radius: 0;
	box-shadow: none;
}

.pn-commerce .wc-block-components-radio-control__label {
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-primary);
}

.pn-commerce .wc-block-components-radio-control__description,
.pn-commerce .wc-block-components-radio-control__secondary-description {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

.pn-commerce .wc-block-components-radio-control__input {
	border-color: var(--line-strong);
	border-radius: var(--radius-full);
}
.pn-commerce .wc-block-components-radio-control__input:checked {
	background: var(--bg-brand);
	border-color: var(--bg-brand);
}

.pn-commerce .wc-block-components-checkbox__mark {
	fill: var(--text-on-brand);
}
.pn-commerce .wc-block-components-checkbox__input[type="checkbox"] {
	border-color: var(--line-strong);
	border-radius: var(--radius-sm);
}
.pn-commerce .wc-block-components-checkbox__input[type="checkbox"]:checked {
	background: var(--bg-brand);
	border-color: var(--bg-brand);
}
.pn-commerce .wc-block-components-checkbox__label {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

/* ── The two columns ──────────────────────────────────────────────────── */

.pn-commerce .wc-block-components-sidebar-layout {
	gap: var(--grid-gap);
}

.pn-commerce .wc-block-components-main {
	padding-right: 0;
}

.pn-commerce .wc-block-components-sidebar {
	padding-left: 0;
}

/* 訂單摘要 follows the form down the page — WooCommerce's own rule, at
   `@container (min-width: 700px) { .wc-block-checkout__sidebar.is-sticky }`,
   and it stops 24px from the top of the *viewport*. This site's header is a
   64px sticky bar, so those 24px are underneath it: measured, the top 40px of
   the sidebar parked behind the glass and 訂單摘要 was cut in half by it.

   The offset is the one .pn-box already sticks to on the product page —
   the bar, then the same 24px of air. Stated outside the container query on
   purpose: `top` on a static element means nothing, so it can be unconditional
   and the sticking itself stays WooCommerce's decision. */
.pn-commerce .wc-block-checkout__sidebar {
	top: calc(var(--pn-header-h) + var(--space-5));
}

@media (min-width: 1024px) {
	/* Seven columns of the twelve to the form, five to what it is paying for,
	   with the grid's own gap between them. WooCommerce ships 50/50 on the
	   cart and 58/42 on the checkout; neither is the theme's grid. */
	.pn-commerce .wc-block-components-main {
		flex: 0 0 calc((100% - var(--grid-gap)) * 7 / 12);
		max-width: calc((100% - var(--grid-gap)) * 7 / 12);
	}
	.pn-commerce .wc-block-components-sidebar {
		flex: 0 0 calc((100% - var(--grid-gap)) * 5 / 12);
		max-width: calc((100% - var(--grid-gap)) * 5 / 12);
	}
}

/* ── 購物車: the table ────────────────────────────────────────────────── */

.pn-commerce .wc-block-cart-items {
	width: 100%;
	border-collapse: collapse;
}

.pn-commerce .wc-block-cart-items__header {
	font-family: var(--font-sans);
	font-size: var(--text-label);
	line-height: var(--lh-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
	text-transform: none;
}

.pn-commerce .wc-block-cart-items__header th {
	padding: 0 0 var(--space-3);
	border-bottom: var(--border-hair);
}

.pn-commerce .wc-block-cart-items__row td {
	padding: var(--space-5) 0;
	border-top: 0;
	border-bottom: var(--border-hair);
	vertical-align: top;
}

/* The picture's column is the picture plus the gap, stated on the <td>: a
   width on the cell alone is a suggestion a table may ignore, and base.css's
   `.pn :is(img, svg, video) { max-width: 100% }` then clamped an 88px
   photograph to the 72px the padding had left it — measured at 72×110, which
   is not 4:5 and was visibly cropping the sides off every product. */
.pn-commerce .wc-block-cart-items__row td.wc-block-cart-item__image {
	width: 112px;
	padding-right: var(--space-5);
}
.pn-commerce .wc-block-cart-item__image img {
	width: 88px;
	max-width: 88px;
	height: 110px;          /* 4:5, the crop inc/woocommerce.php asks for */
	object-fit: cover;
}

/* The stepper is one control, so it has one border. The field inside it is an
   input[type=number] and was picking up the whole field treatment above —
   a bordered, rounded box inside a bordered, rounded box. */
.pn-commerce .wc-block-components-quantity-selector {
	max-width: 112px;
	height: 44px;
	margin: var(--space-4) 0 0;
	border: var(--line-weight) solid var(--line-hair);
	border-radius: var(--radius-sm);
	background: var(--bg-page);
}
.pn-commerce .wc-block-components-quantity-selector::after {
	content: none;
}
.pn-commerce .pn-page__body .wc-block-components-quantity-selector__input {
	min-height: 0;
	height: 42px;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 0;
	font-size: var(--text-small);
	text-align: center;
}
.pn-commerce .wc-block-components-quantity-selector__button {
	width: 34px;
	background: transparent;
	color: var(--text-secondary);
}
.pn-commerce .wc-block-components-quantity-selector__button:hover {
	background: transparent;
	color: var(--text-primary);
}

.pn-commerce .wc-block-cart-item__remove-link {
	color: var(--text-tertiary);
	font-size: var(--text-caption);
}
.pn-commerce .wc-block-cart-item__remove-link:hover {
	color: var(--text-primary);
}

.pn-commerce .wc-block-components-product-name {
	font-family: var(--font-sans);
	font-size: var(--text-body);
	line-height: var(--lh-body);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
}

.pn-commerce .wc-block-components-product-metadata,
.pn-commerce .wc-block-cart-item__prices {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

.pn-commerce .wc-block-cart-item__total {
	text-align: right;
}

/* ── Totals ───────────────────────────────────────────────────────────── */

.pn-commerce .wc-block-components-totals-wrapper {
	padding: var(--space-4) 0;
	border-top: var(--border-hair);
}
.pn-commerce .wc-block-components-totals-wrapper::after {
	content: none;          /* their separator; the border above is ours */
}

/* WooCommerce renders a wrapper for the discount and another for the fees
   whether or not the order has either, so an order with neither drew two
   ruled 33px bands of nothing through the middle of 訂單摘要 — measured, both
   of them empty of elements. A rule across the page has to be separating two
   things. */
.pn-commerce .wc-block-components-totals-wrapper:not(:has(*)) {
	padding: 0;
	border-top: 0;
}

.pn-commerce .wc-block-components-totals-item__label {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	color: var(--text-secondary);
}

.pn-commerce .wc-block-components-totals-item__value {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-primary);
}

/* 總計 is the one number on the page that is the answer, so it is the one
   thing set in the serif. */
.pn-commerce .wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
.pn-commerce .wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-medium);
	color: var(--text-primary);
}

.pn-commerce .wc-block-components-totals-item__description,
.pn-commerce .wc-block-components-totals-footer-item-tax,
.pn-commerce .wc-block-components-totals-footer-item-shipping {
	font-size: var(--text-caption);
	line-height: var(--lh-caption);
	color: var(--text-tertiary);
}

/* 新增折價券 — a disclosure, and the theme has one register for those. */
.pn-commerce .wc-block-components-panel__button {
	padding: var(--space-3) 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
	text-align: left;
}

/* ── 結帳: the order summary ──────────────────────────────────────────── */

.pn-commerce .wc-block-components-order-summary-item {
	padding: var(--space-4) 0;
	border-top: var(--border-hair);
}
.pn-commerce .wc-block-components-order-summary__content > *:first-child {
	border-top: 0;
}

.pn-commerce .wc-block-components-order-summary-item__image img {
	border-radius: 0;
}

/* 0-3-0, to clear the de-rounding rule at the top of this file. */
.pn-commerce .pn-page__body .wc-block-components-order-summary-item__quantity {
	background: var(--bg-muted);
	color: var(--text-primary);
	border: 0;
	border-radius: var(--radius-full);
	font-size: var(--text-caption);
	line-height: 1;
}

.pn-commerce .wc-block-components-order-summary-item__description .wc-block-components-product-name {
	font-size: var(--text-small);
	line-height: var(--lh-small);
}

/* WooCommerce puts a box around 訂單摘要 — all four sides, measured at 1px on
   `.wp-block-woocommerce-checkout-order-summary-block`. A box is not how this
   site says "these belong together"; the rule under the title already says it,
   and every other total on the page is separated by a rule and nothing else. */
.pn-commerce .wp-block-woocommerce-checkout-order-summary-block,
.pn-commerce .wp-block-woocommerce-cart-order-summary-block {
	padding: 0;
	border: 0;
	background: transparent;
}

/* The terms line above 下單購買. */
.pn-commerce .wc-block-checkout__terms {
	margin: 0;
	padding: var(--space-5) 0 0;
	font-size: var(--text-caption);
	line-height: var(--lh-caption);
	color: var(--text-secondary);
}
.pn-commerce .wc-block-checkout__terms--with-separator {
	border-top: var(--border-hair);
}

.pn-commerce .wc-block-checkout__actions {
	padding-top: var(--space-5);
}

.pn-commerce .wc-block-checkout__guest-checkout-notice {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

/* ── Notices ──────────────────────────────────────────────────────────── */

/* A notice is something that interrupts: an error, a warning, a thing that
   went wrong. 訂單完成's 「謝謝，我們已經收到您的訂單。」 is none of those — it is
   the page's opening line — so it is not on this list, and is set as a lede at
   the bottom of the file instead. What *is* on the list is
   `.woocommerce-notice--error`, which is the same markup carrying the opposite
   news: the order failed, pay again. That one genuinely interrupts.

   The icon comes off every `.woocommerce-notice`, whichever it is. Blocksy
   draws one from the `woo` icon font, absolutely positioned at left:20px, and
   leaves room for it with `padding: 1em 2em 1em 3.5em`; base.css strips padding
   from a bare `<p>` inside `.pn`. Either half alone is harmless — together the
   room went, the icon stayed, and it printed on top of the 謝. */
.pn-commerce :is(.wc-block-components-notice-banner, .woocommerce-notice--error, .woocommerce-message, .woocommerce-info, .woocommerce-error) {
	margin: 0 0 var(--space-5);
	padding: var(--space-4);
	background: var(--bg-subtle);
	color: var(--text-primary);
	border: 0;
	border-left: 2px solid var(--line-strong);
	border-radius: 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
}
.pn-commerce :is(.woocommerce-notice, .woocommerce-message, .woocommerce-info, .woocommerce-error)::before {
	content: none;          /* Blocksy's and WooCommerce's icon fonts */
}
.pn-commerce .wc-block-components-notice-banner.is-error,
.pn-commerce .woocommerce-notice--error,
.pn-commerce .woocommerce-error {
	border-left-color: var(--error);
}

/* ── 我的帳戶 ─────────────────────────────────────────────────────────────
   The classic `[woocommerce_my_account]` shortcode — WooCommerce has no block
   for this page — so unlike the cart and the checkout it *is* templatable, and
   from this round two of its templates are the theme's own. Which two, and
   why, is written out at the head of inc/my-account.php; the short version is
   that the left column was never ours to style. Blocksy wrapped the menu in a
   `.ct-acount-nav` card of its own making — 5px corners, a drop shadow, a
   white ground, `width: 20%` — and no selector here had ever named it.

   What that card held: 55px fixed rows, 20px of inset padding, a glyph from a
   webfont called `woo` in front of every label, and a filled bar in Blocksy's
   brand colour under the current item and under the pointer. Six rounded,
   shadowed, iconned, highlighted rows, on a site whose entire visual grammar
   is a hairline and a dot.

   So: no card, no icons, no fill. A row is a rule. The current row is marked
   by a dot, which is the mark this theme uses for a current thing — the footer
   already marks the current page of a column exactly this way, indentation and
   all, and the account menu is the same problem. ─────────────────────────── */

/* Blocksy injects `ct-woo-account` onto the shortcode's own wrapper through
   `do_shortcode_tag`, and the one rule attached to it is `display: flex` above
   768px. That wrapper's children are not the two columns — they are the
   notices wrapper and then everything else — so the flex row it makes puts
   notices *beside* the page. Left alone it went unnoticed only because an
   account page rarely carries a notice; 儲存變更 makes one every time.
   0-3-0, over the 0-1-0 it is answering. */
.pn-commerce .woocommerce.ct-woo-account {
	display: block;
}

/* ── The two columns: the menu and the page ───────────────────────────── */

/* Stacked until there is room, menu first — which is the reading order too,
   so nothing has to be reordered. */
.pn-account {
	display: grid;
	gap: var(--space-7);
}

@media (min-width: 1024px) {
	/* Three of the theme's twelve columns to the menu, nine to the page. The
	   cart and the checkout split 7/5 on the same grid; a list of six short
	   words needs a quarter of that pair's narrower column, and 帳戶詳細資料 —
	   the longest label WooCommerce ships — sets the floor at about 100px of
	   text inside a 296px column. Blocksy's own was `20%, min 220px`, which is
	   a width rather than a column of anything. */
	.pn-account {
		grid-template-columns:
			calc((100% - 11 * var(--grid-gap)) * 3 / 12 + 2 * var(--grid-gap))
			1fr;
		gap: var(--grid-gap);
		align-items: start;
	}
}

/* Both columns: a grid item is `min-width: auto` by default, which is the
   width of its widest unbreakable content — and 訂單 is a five-column table.
   Without this the table pushes the grid wider than the container and the page
   scrolls sideways. */
.pn-account__nav,
.pn-account__content {
	min-width: 0;
}

/* ── The menu ─────────────────────────────────────────────────────────── */

.pn-commerce .pn-account__menu {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: var(--border-hair);
}

/* The type lives on the row rather than on the link, so the `1em` the dot is
   centred against below is the row's own 14px and not something inherited from
   further up. */
.pn-commerce .pn-account__item {
	position: relative;
	border-bottom: var(--border-hair);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	/* Every row is indented by the dot's width, not just the marked one, so the
	   left text edge survives the mark moving. The footer's current-page dot
	   does the same thing for the same reason. */
	padding-left: calc(var(--dot-size) + var(--space-2));
}

/* The mark. Centred on the first line by half-leading and the row's own top
   padding — 16 + (14 × 1.5 − 6) / 2 = 23.5, which puts the dot's middle at
   26.5 in a 53px row. Not nudged by eye. */
.pn-commerce .pn-account__item.is-active::before {
	content: "";
	position: absolute;
	left: 0;
	top: calc(var(--space-4) + (1em * var(--lh-small) - var(--dot-size)) / 2);
	width: var(--dot-size);
	height: var(--dot-size);
	border-radius: var(--radius-full);
	background: var(--dot-brand);
}

/* 0-3-0, which is what it takes to beat Blocksy's
   `.woocommerce-MyAccount-navigation ul li a` at 0-1-3 — one class of ours
   short of it without the scope. `height` is stated because that rule sets a
   fixed 55px, and a row in this theme is as tall as what is in it.

   `border: 0` is stated for a subtler one, and it was measured rather than
   guessed: Blocksy also rules under the *anchor*, at
   `li:not(:last-child) a`. With the rule under the row above it, every row
   carried two hairlines — one the width of the row and one inset by the dot's
   indent, 1px apart. In the harness the row measured 55 where the arithmetic
   said 54, which is how it was found. */
.pn-commerce .pn-account__nav .pn-account__link {
	display: block;
	height: auto;
	padding: var(--space-4) 0;
	border: 0;
	font-family: var(--font-sans);
	font-size: inherit;
	line-height: inherit;
	font-weight: var(--weight-regular);
	color: var(--text-secondary);
	text-decoration: none;
	background: none;
	transition: opacity var(--dur-fast) var(--ease-out);
}

/* The webfont glyph in front of every label. 0-3-1 over the 0-2-3 of
   `.woocommerce-MyAccount-navigation ul .woocommerce-MyAccount-navigation-link--orders a:before`,
   which is the specificity this whole template override exists to clear: with
   WooCommerce's classes alone there is no rule that can be written here to
   take an icon off. */
.pn-commerce .pn-account__nav .pn-account__link::before {
	content: none;
}

/* Blocksy fills the row instead. 0-5-0 over its 0-2-3 — the pointer says where
   it is by the same means every other link on this site does. */
.pn-commerce .pn-account__nav .pn-account__item:hover .pn-account__link,
.pn-commerce .pn-account__nav .pn-account__link:focus-visible {
	background: none;
	color: var(--text-primary);
	opacity: var(--hover-opacity);
}

.pn-commerce .pn-account__nav .pn-account__item.is-active .pn-account__link {
	color: var(--text-primary);
	background: none;
	opacity: 1;
}

/* ── 儀表板 ───────────────────────────────────────────────────────────── */

/* Two sentences and a way on. What used to be here is written out at the head
   of woocommerce/myaccount/dashboard.php. */
.pn-account__intro {
	margin: 0;
}

/* The greeting is the page's one serif line, the way 訂單完成's opening
   sentence is: it is the answer to who this page belongs to. */
.pn-commerce .pn-account__greeting {
	margin: 0;
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
}

.pn-commerce .pn-account__member {
	margin: var(--space-4) 0 0;
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-secondary);
}

.pn-commerce .pn-account__more {
	margin: var(--space-5) 0 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
}

/* ── Headings, forms, fields ──────────────────────────────────────────── */

/* The classic shortcode. WooCommerce draws its own heading over the login
   form; it is the name of the one thing on the page, so it is a heading. */
.pn-commerce .woocommerce > h2,
.pn-commerce .woocommerce h2 {
	margin: 0 0 var(--space-5);
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-medium);
	color: var(--text-primary);
}

.pn-commerce .woocommerce-form-row,
.pn-commerce .woocommerce .form-row {
	margin: 0 0 var(--space-5);
	padding: 0;
}

.pn-commerce .woocommerce label {
	display: block;
	margin-bottom: var(--space-2);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

.pn-commerce .woocommerce .required {
	color: var(--error);
	text-decoration: none;
}

/* 名 and 姓 on one line, 帳單地址's first pair likewise. WooCommerce's markup
   is built for floats — every pair is followed by `<div class="clear">` — and
   WooCommerce's own stylesheet, which would have floated them, is one of the
   four Blocksy does not load. So the theme does it, in the shape the markup
   already expects. */
@media (min-width: 768px) {
	.pn-commerce .woocommerce .form-row-first {
		float: left;
		width: calc(50% - var(--grid-gap) / 2);
	}
	.pn-commerce .woocommerce .form-row-last {
		float: right;
		width: calc(50% - var(--grid-gap) / 2);
	}
}

.pn-commerce .woocommerce .clear {
	clear: both;
}

/* 變更密碼 on 帳戶詳細資料 — the one `<fieldset>` WooCommerce ships. A fieldset
   is a section; a section here opens with a rule and its name. */
.pn-commerce .woocommerce fieldset {
	margin: var(--space-7) 0 var(--space-6);
	padding: var(--space-6) 0 0;
	border: 0;
	border-top: var(--border-hair);
}

/* `float` is the load-bearing line, and it is here because of what a `<legend>`
   is: the browser lays it *inside* the fieldset's block-start border, and
   interrupts the border to make room. With a hairline on top, the rule ran up
   to 變更密碼, stopped, and started again past it — a broken line, level with
   the heading instead of above it. Measured: the legend's top and the
   fieldset's top were the same 615.4.

   Floating it takes it out of the border entirely: the rule draws unbroken and
   the name sits under it, in the fieldset's own 32px of padding. `width: 100%`
   so the rows that follow clear it rather than wrapping beside it. */
.pn-commerce .woocommerce fieldset legend {
	float: left;
	width: 100%;
	margin: 0 0 var(--space-5);
	padding: 0;
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-medium);
	color: var(--text-primary);
}

/* The note under 顯示名稱. Blocksy sets it 13px at 80% opacity — a fourth size
   and a colour that is not in the palette. It is a caption; there is a
   register for that. 0-2-1 over its 0-1-1. */
.pn-commerce .woocommerce-MyAccount-content em {
	font-size: var(--text-caption);
	line-height: var(--lh-caption);
	font-style: normal;
	opacity: 1;
	color: var(--text-tertiary);
}

.pn-commerce .woocommerce-form-login__rememberme {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	margin-bottom: var(--space-5);
}
.pn-commerce .woocommerce-form-login__rememberme input {
	width: auto;
	min-height: 0;
}

.pn-commerce .woocommerce-LostPassword {
	margin: var(--space-4) 0 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
}

/* ── 地址 ─────────────────────────────────────────────────────────────── */

.pn-commerce .woocommerce-Addresses {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-7);
	margin-top: var(--space-6);
}

@media (min-width: 768px) {
	.pn-commerce .woocommerce-Addresses {
		grid-template-columns: 1fr 1fr;
		gap: var(--grid-gap);
	}
}

/* Each address ships in a card: Blocksy's `.woocommerce-Addresses > *` is
   `padding: 1.5em; border-radius: 5px; border: 1px dashed`, which is the same
   dashed box it puts around the address on 訂單完成 and which that section of
   this file already takes off. Same answer here. 0-2-0 over its 0-1-0. */
.pn-commerce .woocommerce-Addresses > * {
	padding: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
}

/* The name of the address and the way to change it are one line: the link is
   what you do to the thing the heading names, not a separate thought. The rule
   under them is where the address starts.

   0-3-0 rather than the 0-2-0 this needs on its own, because Blocksy's
   `.woocommerce-Addresses .woocommerce-Address-title` is 0-2-0 too and carries
   a `margin-bottom: 20px`. That margin collapsed with the address's own 16px
   top margin and won it — measured at 20, which is how it was noticed. */
.pn-commerce .woocommerce .woocommerce-Address-title {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--space-4);
	margin: 0;
	padding-bottom: var(--space-3);
	border-bottom: var(--border-hair);
}

/* 0-3-1, over `.pn-commerce .woocommerce h2` above — which is the rule that
   gives this heading its size, and also gives it a 24px bottom margin that has
   no business inside a flex row. */
.pn-commerce .woocommerce .woocommerce-Address-title h2 {
	margin: 0;
}

.pn-commerce .woocommerce-Address-title .edit {
	flex: none;
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-link);
}

/* 0-2-1, over `.woocommerce-Addresses address { font-size: 15px; opacity: .8 }`
   — a fourth size and a faded ink, on the one thing on the page a courier
   reads. */
.pn-commerce .woocommerce-Address address {
	margin: var(--space-4) 0 0;
	font-size: var(--text-body);
	line-height: var(--lh-body);
	font-style: normal;
	opacity: 1;
	color: var(--text-primary);
}

/* ── Tables: 訂單 and 下載 ────────────────────────────────────────────── */

/* `--theme-table-font-size` is not decoration either. The cells came out 15px
   against the table's own 14, and the reason is two rules in Blocksy: its
   `table.shop_table` sets `--theme-table-font-size: 15px`, and its
   `table, th, td` — 0-0-1, the lowest weight there is — reads that property
   back on every cell. A size on the table alone is only an inheritance, and an
   explicit 0-0-1 rule beats an inheritance every time.

   Redefining the property is the same move the head of this file makes for
   `--wp--preset--font-size--medium`, and it is better than stating a size on
   `:is(th, td)` here: that was tried, it worked, and it silently took the
   16px off 訂單完成's totals foot two hundred lines below, because a rule
   carrying three classes outranks one carrying two. A custom property changes
   what the lowest rule resolves to and leaves every rule above it alone.

   `line-height` inherits and `table, th, td` does not set it, so the table's
   own is enough — and `--lh-small` is unitless, so the 16px tfoot works it out
   at 24 while a 14px cell gets 21. */
.pn-commerce .woocommerce table.shop_table {
	--theme-table-font-size: var(--text-small);
	width: 100%;
	border: 0;
	border-collapse: collapse;
	font-size: var(--text-small);
	line-height: var(--lh-small);
}
.pn-commerce .woocommerce table.shop_table :is(th, td) {
	padding: var(--space-4) var(--space-4) var(--space-4) 0;
	background: transparent;
	border: 0;
	border-bottom: var(--border-hair);
	text-align: left;
}
.pn-commerce .woocommerce table.shop_table th {
	font-size: var(--text-label);
	line-height: var(--lh-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
}
/* A row's own cells are `<th scope="row">` for the order number, which is
   correct markup and not a header's type. */
.pn-commerce .woocommerce table.shop_table tbody th {
	font-size: var(--text-small);
	/* Stated for the same reason as the size: the rule above hands every `th`
	   the label's tighter 1.3, and an order number set at 18.2 next to a date
	   set at 21 is one row on two leadings. */
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	letter-spacing: 0;
	color: var(--text-primary);
}

/* 檢視 at the end of an order's row. It arrives as `.woocommerce-button
   .button`, which the button rule at the top of this file turns into a 44px
   brand-coloured block — six of them stacked down the right of a table of six
   orders, each one louder than the order it belongs to. A row in a record gets
   a link.

   0-5-0, because the rule it is answering is 0-4-0: two classes of scope, the
   `:is()` and the `:not()`, each counting once. The `:not(.is-link)` here is
   carried for the weight, and is true of these anyway. */
.pn-commerce .pn-page__body .woocommerce-orders-table__cell-order-actions .button:not(.is-link),
.pn-commerce .pn-page__body .woocommerce-orders-table__cell-download-file .button:not(.is-link) {
	display: inline;
	min-height: 0;
	padding: 0;
	background: none;
	border: 0;
	color: var(--text-link);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	text-decoration: none;
}

.pn-commerce .woocommerce-orders-table__cell-order-actions .button + .button {
	margin-left: var(--space-4);
}

/* Small screens. WooCommerce ships a stylesheet for exactly this —
   woocommerce-smallscreen.css, which reads the `data-title` on every cell —
   and Blocksy does not load it, or either of WooCommerce's other two classic
   stylesheets. So a five-column table of orders was a five-column table of
   orders on a 375px phone. The label comes from the same attribute
   WooCommerce's own rules read. */
@media (max-width: 767.98px) {
	.pn-commerce .woocommerce table.shop_table_responsive thead {
		display: none;
	}

	.pn-commerce .woocommerce table.shop_table_responsive tr {
		display: block;
		border-bottom: var(--border-hair);
	}

	.pn-commerce .woocommerce table.shop_table_responsive :is(th, td) {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		gap: var(--space-5);
		padding: var(--space-2) 0;
		border: 0;
		text-align: right;
	}

	.pn-commerce .woocommerce table.shop_table_responsive tr > :first-child {
		padding-top: var(--space-4);
	}
	.pn-commerce .woocommerce table.shop_table_responsive tr > :last-child {
		padding-bottom: var(--space-4);
	}

	.pn-commerce .woocommerce table.shop_table_responsive :is(th, td)::before {
		content: attr(data-title);
		flex: none;
		font-size: var(--text-label);
		font-weight: var(--weight-medium);
		letter-spacing: var(--ls-label);
		color: var(--text-tertiary);
		text-align: left;
	}
}

.pn-commerce .woocommerce-pagination {
	display: flex;
	gap: var(--space-4);
	margin-top: var(--space-6);
}

/* 上一頁 · 下一頁 arrive as `.woocommerce-button .button` too, so the button
   rule makes them two solid brand-coloured blocks under a table of hairlines.
   They are not what this page is for — the orders are — so they take the
   outline weight base.css already defines for a button that is a control
   rather than an answer. Same 0-5-0 the row action needs, and for the same
   reason. */
.pn-commerce .pn-page__body .woocommerce-pagination .button:not(.is-link) {
	background: transparent;
	color: var(--text-primary);
	border-color: var(--line-strong);
}
.pn-commerce .pn-page__body .woocommerce-pagination .button:not(.is-link):hover {
	background: transparent;
	color: var(--text-primary);
	border-color: var(--line-strong);
}

/* ── 註冊 ──────────────────────────────────────────────────────────────
   /my-account/register/ — an account endpoint, so everything above is already
   in force and this adds only what a page asking someone to join needs that a
   page asking them to log in does not: a reason, and a measure.

   我的帳戶 runs the full container, which is right for a dashboard of orders
   and addresses and wrong for two fields.

   450px, and it is not an invented number: it is what 登入 already measures.
   Blocksy caps `form.login` there and nothing in this theme ever overrode it,
   so every visitor who has seen this site's login form has seen a 450px
   column — and a 註冊 page six of the twelve columns wide next to it measured
   628, which is two doors into one room with different door frames. The whole
   block takes the width, not just the form, so the lead, the fields and the
   way out share one left edge.

   Centred, for the same reason and off the same measurement: Blocksy gives
   `form.login` `margin-inline: auto`, so 登入 sits at x 495 in a 1440 viewport
   with 415px either side, while 註冊 was hard against the container's left
   edge at x 80. Two pages one click apart, the form in a different place on
   each. The text inside stays left-aligned, which is what 登入 does too —
   centring the column is not centring the writing.

   The page's h1 is *not* centred, on either page. `.pn-page__title` is shared
   chrome and 我的帳戶 has always sat at the container edge above a centred
   form; matching 登入 exactly means inheriting that, and changing it would
   change the page that was signed off.

   Blocksy's rule reaches `form.login` only, so this does not double up on it
   and 登入 is untouched. If that bundle ever stops setting it, these are the
   two numbers to give it. ─────────────────────────────────────────────── */

.pn-commerce--register .pn-register {
	max-width: 450px;
	margin-inline: auto;
}

/* The one sentence carried over from 長青會員. Set as that page sets it, at
   the body size and the Chinese measure, because it is the same sentence and
   a reader arriving from the button has just read it there. */
.pn-commerce--register .pn-register__lead {
	margin: 0 0 var(--space-7);
	max-width: 34em;
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-secondary);
}

/* Only rendered when wp-admin generates passwords instead of asking for one —
   see woocommerce/myaccount/form-register.php. It is an aside about what
   happens next, not a field. */
.pn-commerce--register .pn-register__note {
	margin: 0 0 var(--space-5);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-tertiary);
}

/* ── 會員條款 · 個資告知 ──────────────────────────────────────────────────
   The one row on this form that is a sentence rather than a field, and it is
   set as a sentence: the box and the words on one line, the words at the size
   the form's own labels use, and the two document names as links inside the
   sentence rather than a row of links underneath it. A reader ticking this is
   agreeing to something, and something you can read in a line is the only
   thing anybody agrees to.

   `flex-start`, not `center`: the sentence is one line in the 450px column and
   two at 375, and a vertically centred box would drop into the middle of the
   paragraph on a phone. It belongs against the first line, where the reading
   starts, and it stays there at both widths.

   `margin: 0` on the box, and that is measured rather than assumed. A 16px box
   at the top of a 21px line already lands its centre on 864 against the line's
   863.5 — half a pixel, in Chinese, where the glyphs fill the em box. An
   optical nudge was tried first at 0.25em and pushed it four pixels low.

   The other two declarations are the ones 登入's rememberme already needs,
   against the same generic reach from Blocksy and WooCommerce. */

.pn-commerce--register .woocommerce .pn-register__consent {
	margin: var(--space-6) 0 0;
}

.pn-commerce--register .woocommerce .pn-register__consent-label {
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
	margin: 0;
	cursor: pointer;
}

.pn-commerce--register .pn-register__consent-label input[type="checkbox"] {
	flex: none;
	width: auto;
	min-height: 0;
	margin: 0;
}

.pn-commerce--register .pn-register__consent-text {
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

/* The submit row. 登入 gets this margin from its rememberme label; here the
   consent above provides the same distance, and the rule stays because the
   form still renders without a consent — no policy pages, no box.

   Three classes, because `.pn-commerce .woocommerce .form-row` above is three
   and a two-class rule lost to it — measured: margin-top computed 0. */
.pn-commerce--register .woocommerce .pn-register__submit {
	margin: var(--space-6) 0 0;
}

/* Full width on a phone, the way 長青會員's 免費成為長青會員 is — the same
   button, one page earlier, and 106px of it floating in a 327px column is the
   one thing on this page that would not look like the rest of the site. */
@media (max-width: 767px) {
	.pn-commerce--register .woocommerce .woocommerce-form-register__submit {
		width: 100%;
	}
}

/* ── The line between the two doors ───────────────────────────────────────
   還不是會員？ under 登入, and 已經是會員？登入 · 會員權益 under 註冊. The same
   class both ways: it is one component — the way out of the form you are not
   here for — and it reads as one because it is set as one.

   A rule above it, because it is the only place on either page where the page
   stops being the form. Column on a phone and a row above it, for the reason
   長青會員's CTA pair wraps: 375px does not hold two links on a line. ─────── */
.pn-commerce .pn-account__switch {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	margin: var(--space-7) 0 0;
	padding-top: var(--space-5);
	border-top: var(--border-hair);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

@media (min-width: 768px) {
	.pn-commerce .pn-account__switch {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: baseline;
		gap: var(--space-5);
	}
}

/* ── Saying whether it worked ──────────────────────────────────────────
   `woocommerce_output_all_notices` prints into `.woocommerce-notices-wrapper`,
   which WooCommerce puts *outside* the form — so a 「兩次輸入的密碼不一致」 that
   belongs to one field was measured 1280px wide over a 450px column, floating
   free of the thing it is about. True of 登入 as well, and invisible there
   until now only because nothing on that page had produced a notice.

   The wrapper takes the form's own column, so the answer sits over the
   question. `body:not(.logged-in)` because this is the logged-out half of
   我的帳戶 — 登入, 註冊, 忘記密碼. The dashboard, the orders and the addresses
   run the full container and their notices should too. That is WordPress's own
   class, not Blocksy's `ct-woo-unauthorized`, which would be a second theme's
   markup holding up this one's layout. ─────────────────────────────────── */
body:not(.logged-in).pn-commerce--account .woocommerce-notices-wrapper {
	max-width: 450px;
	margin-inline: auto;
}

/* Colour is the whole affordance here. `.pn-link` is `--text-primary` with an
   opacity fade and nothing else — no underline — so the `→` after each of
   these was doing all the work of saying "this goes somewhere". The arrows are
   gone and `--text-link` says it instead: the green the rest of the site
   already uses for a link in running text (policy.css, partners.css,
   shop.css), and the one token that has an inverse-theme value ready if either
   page ever lands on dark.

   Three classes to beat `.pn .pn-link`, and `opacity: 1` because a colour
   change and a fade at once reads as neither.

   The consent's two document names joined this rule in round 29 for a sharper
   version of the same reason: those are not a way out of the form, they are
   the things being agreed to, and a name you cannot tell is a link is a
   document nobody opens before they tick.

   儀表板's 會員權益 joined in round 30 for the plainest version of it: one
   `.pn-link` alone on a line under two sentences of prose, which without the
   colour is a line of prose. Measured first —
   `rgb(22, 36, 28)`, the same ink as the sentence above it. */
.pn-commerce .pn-account__switch .pn-link,
.pn-commerce .pn-account__more .pn-link,
.pn-commerce--register .pn-register__consent-text .pn-link {
	color: var(--text-link);
}
.pn-commerce .pn-account__switch .pn-link:hover,
.pn-commerce .pn-account__switch .pn-link:focus-visible,
.pn-commerce .pn-account__more .pn-link:hover,
.pn-commerce .pn-account__more .pn-link:focus-visible,
.pn-commerce--register .pn-register__consent-text .pn-link:hover,
.pn-commerce--register .pn-register__consent-text .pn-link:focus-visible {
	opacity: 1;
	color: var(--text-link-hover);
}

/* ── 訂單完成 ─────────────────────────────────────────────────────────────
   The page a buyer sees once, for about fifteen seconds, and then again in a
   week when they want to know what they ordered. It has three jobs and they
   are not equal: say it worked, hand over the reference they will quote, and
   let them leave. WooCommerce ships all three as one undifferentiated column
   of <p>, <ul>, <table>, so the whole design here is deciding which part is
   which and giving each its own register.

   It is classic PHP, not a block — templates/checkout/thankyou.php and the
   four it pulls in. The theme still does not override them: the markup below
   is WooCommerce 11.1.0's own, and this is type, colour and rules over it, the
   way the rest of this file works. tools/preview/commerce-received.html is a
   hand transcription of those templates for measuring against.

   Two of those five templates are also what 我的帳戶 → 訂單 → 檢視 renders, so
   the rules below split in two by scope, and the scope is the whole of the
   distinction:

     · `.pn-commerce--order` is the order itself — the itemisation, the totals
       foot, the two addresses. True wherever an order is written out, which is
       both pages (pn_commerce_body_class(), inc/commerce.php). Until this
       round these were `--received` too, which meant a buyer reading the order
       back a week later got WooCommerce's defaults for it: a boxed address in
       synthesised italics and a tfoot set heavier than its own 總計.
     · `.pn-commerce--received` is what only happens once — the thank-you
       sentence, the four-fact overview, whatever the gateway needs saying, and
       the way back to the shop. ──────────────────────────────────────────── */

/* The opening line. Not a notice — the answer to the only question the buyer
   has — so it is set the way a story's first line is, and the page's one
   serif sentence below the title. */
.pn-commerce--received .woocommerce-thankyou-order-received {
	/* `display: block` for the same reason the overview needs it: the cascade
	   underneath lays a notice out as a flex container, and one text node in a
	   flex container is an anonymous item that does not sit on the line box it
	   draws. Measured — one 35px line of text in a 60px box, a half-line of
	   empty air under the sentence that no margin accounted for.

	   `min-height: 0` for the other half of the same story: the notice carries
	   a 60px minimum so its icon has somewhere to sit. The icon is gone and the
	   box still measured 60px around one 30px line. */
	display: block;
	min-height: 0;
	margin: 0 0 var(--space-7);
	padding: 0;
	background: transparent;
	border: 0;
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
}

/* The four facts, as the record this site keeps everywhere else: a rule, then
   a row per fact, label left and value right. Deliberately the same shape as
   訂單摘要's totals, which this buyer was looking at a few seconds ago.

   The label is a bare text node and the value a <strong>, so the <li> carries
   the label's type and the <strong> overrides it — no wrapper to hook, and
   none needed. */
.pn-commerce--received .woocommerce-order-overview {
	/* `display: block` is the load-bearing line. The cascade under this one
	   lays the four facts out as a two-column grid — measured at
	   `grid-template-columns: 361px 361px`, 訂單編號 beside 日期 and 總計 beside
	   付款方式 — which puts two label/value pairs on one line and leaves the
	   serif 總計 stranded in the middle of a row. One fact per row is what
	   訂單摘要 does three clicks earlier. */
	display: block;
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: var(--border-hair);
}

.pn-commerce--received .woocommerce-order-overview li {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--space-4);
	margin: 0;
	padding: var(--space-4) 0;
	border-bottom: var(--border-hair);
	font-size: var(--text-label);
	line-height: var(--lh-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
	text-transform: none;
}

.pn-commerce--received .woocommerce-order-overview li strong {
	font-size: var(--text-body);
	line-height: var(--lh-body);
	font-weight: var(--weight-regular);
	letter-spacing: 0;
	color: var(--text-primary);
	text-align: right;
}

/* 總計 is the one number on the page that is the answer — the same rule
   訂單摘要 follows, and the reason the 總計 in the table below is emphasised
   but not set in the serif. Two serif numbers would be two answers. */
/* 0-3-2: `.woocommerce-order-overview li strong` above is 0-2-2, and the
   modifier class on its own would have been 0-2-1 — lower, not higher. */
.pn-commerce--received .woocommerce-order-overview li.woocommerce-order-overview__total strong {
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-medium);
}

/* What the gateway wants next — 貨到付款's 「請在收到商品時備妥現金」, and the
   代碼 / 條碼 / 匯款帳號 that 綠界's gateways print in the same place. This is
   the one thing on the page the buyer has to *act* on, and it arrives as a
   bare <p> with no class of any kind, straight out of wpautop() in the
   gateway's thankyou_page(). Every other child of .woocommerce-order is
   classed, so an unclassed one is always a gateway talking.

   It gets the shape the thank-you sentence wrongly had: the quiet ground and
   the 2px rule this theme gives anything that interrupts. Here it earns it. */
.pn-commerce--received .woocommerce-order > p:not([class]) {
	margin: var(--space-6) 0 0;
	padding: var(--space-4);
	background: var(--bg-subtle);
	border-left: 2px solid var(--line-strong);
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-primary);
}

/* 訂單詳細資料 opens with a rule. What is above it is the four facts and
   whatever the gateway had to say — a different matter — and the rule is
   where the record starts. */
.pn-commerce--order .woocommerce-order-details {
	display: block;
	margin-top: var(--space-7);
	padding-top: var(--space-7);
	border-top: var(--border-hair);
}

/* 帳單地址 does not get one. The itemisation directly above it already ends
   in the 總計 row's own hairline, so a second rule a few dozen pixels below
   the first is a line drawn twice — and a line in this theme has to signal
   something. Air separates them instead, and more of it than the rule needed
   to do the same work. */
.pn-commerce--order .woocommerce-customer-details {
	display: block;
	margin-top: var(--space-8);
}

.pn-commerce--order .woocommerce-order-details__title {
	margin: 0 0 var(--space-5);
}

/* The itemisation. `.woocommerce table.shop_table` at the top of the 我的帳戶
   section already sets the type and the hairlines; what it does not know is
   that this table has two columns and the right one is money. */
.pn-commerce--order table.order_details :is(th, td):last-child {
	text-align: right;
}

.pn-commerce--order table.order_details tfoot th {
	font-size: var(--text-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
}

.pn-commerce--order table.order_details tfoot td {
	/* The weight is stated, not left alone: the cascade underneath sets every
	   tfoot cell to 600, which made 小計, 運送方式 and 付款方式 heavier than the
	   總計 below them — the emphasis exactly backwards. */
	font-size: var(--text-body);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
}

/* The last line of the itemisation is 總計 again. Emphasised, because it is
   where the eye stops; not serif, because the answer is already given above. */
.pn-commerce--order table.order_details tfoot tr:last-child :is(th, td) {
	font-weight: var(--weight-medium);
	color: var(--text-primary);
}

.pn-commerce--order table.order_details .product-quantity {
	font-weight: var(--weight-regular);
	color: var(--text-secondary);
}

.pn-commerce--order table.order_details :is(.shipped_via, .includes_tax) {
	display: inline;
	font-size: var(--text-caption);
	line-height: var(--lh-caption);
	color: var(--text-tertiary);
}

/* 帳單地址 and 運送地址. These are not sections of their own weight — they are
   two values with names — so the name takes the label register the table
   headers use, and the address itself is the body text under it. */
.pn-commerce--order .woocommerce-columns--addresses {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-6);
}

@media (min-width: 768px) {
	.pn-commerce--order .woocommerce-columns--addresses {
		grid-template-columns: 1fr 1fr;
		gap: var(--grid-gap);
	}
}

/* 0-3-0, over the `.pn-commerce .woocommerce h2` in the 我的帳戶 section that
   makes every h2 in classic WooCommerce markup a serif heading. 訂單詳細資料
   wants that rule and keeps it; these two do not. */
.pn-commerce--order .woocommerce .woocommerce-column__title {
	margin: 0 0 var(--space-3);
	font-family: var(--font-sans);
	font-size: var(--text-label);
	line-height: var(--lh-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
	text-transform: none;
}

/* A browser sets <address> in italics by default, which on 忠孝東路一段1號 is a
   synthesised slant of a Chinese face and reads as a mistake. */
.pn-commerce--order address {
	/* Blocksy boxes an address — `padding: 1.5em; border-radius: 5px; border:
	   1px dashed` — and the de-rounding rule at the top of this file does not
	   reach it, because `address` is not one of the elements it lists. There
	   are no boxes on this page; the label above the address already says what
	   it is. */
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	font-style: normal;
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-primary);
}

.pn-commerce--order address :is(.woocommerce-customer-details--phone, .woocommerce-customer-details--email) {
	margin: 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
	color: var(--text-secondary);
}

/* The way out. Without it the page is a cul-de-sac: every link on it goes to
   the order that was just placed. */
.pn-commerce--received .pn-received__back {
	margin: var(--space-7) 0 0;
	padding-top: var(--space-7);
	border-top: var(--border-hair);
}

/* ── 收藏 ─────────────────────────────────────────────────────────────────
   The wishlist page, which is TI WooCommerce Wishlist's and joins this
   stylesheet through `perennial_is_commerce` — inc/wishlist.php says why from
   its own end. Structurally it is 購物車 with different columns, and the whole
   point of bringing it here is that almost nothing below is new: the table,
   the hairlines, the label register at the head, the small-screen stacking and
   the notice are the rules two hundred lines above, reached by putting
   WooCommerce's own `shop_table shop_table_responsive` on the plugin's table
   in woocommerce/ti-wishlist.php.

   What is here is the four things that table has and an orders table does not:
   a picture, a price, an add, and a way to take a row off. ──────────────── */

/* The plugin's wrapper. `.tinv-wishlist` has a `clear: both` float clearer of
   its own and its stylesheet gives the page a bottom margin we do not want
   under the last hairline. */
.pn-commerce--wishlist .tinv-wishlist,
.pn-commerce--wishlist .pn-wish__form {
	margin: 0;
}

/* The list's name, when there is one. Most shops have exactly one list and it
   is called whatever the plugin called it, so ti-wishlist-header.php prints
   nothing at all in that case and this styles the other one: a named list,
   under a page already named 收藏, which makes it the step below. */
.pn-commerce--wishlist .pn-wish__head:not(:empty) {
	margin-bottom: var(--space-6);
}

.pn-commerce .pn-wish__title {
	margin: 0;
	font-family: var(--font-sans);
	font-size: var(--text-label);
	line-height: var(--lh-label);
	font-weight: var(--weight-medium);
	letter-spacing: var(--ls-label);
	color: var(--text-tertiary);
}

/* ── Empty, and not found ─────────────────────────────────────────────── */

/* An empty wishlist is not a notice. It is the true state of this page for
   everybody who has not saved anything, which is most people arriving on it —
   so it is set the way 訂單完成's opening line is, as the page's own sentence,
   rather than in the bordered ground this file gives things that interrupt.
   〈找不到這個收藏〉 is the other kind and keeps `.woocommerce-info`. */
.pn-commerce .pn-wish__empty {
	margin: 0;
	font-family: var(--font-serif);
	font-size: var(--pn-text-h3);
	line-height: var(--lh-h3);
	letter-spacing: var(--ls-h3);
	font-weight: var(--weight-regular);
	color: var(--text-primary);
}

.pn-commerce .pn-wish__back {
	margin: var(--space-6) 0 0;
}

/* ── The table ────────────────────────────────────────────────────────── */

/* The picture's column is the picture plus the gap, stated on the cell — the
   same 112 / 88 × 110 購物車 uses, and stated here for the same reason it is
   stated there: base.css clamps an image to its cell, so a width left to the
   table crops the sides off every product. 4:5 is the crop
   inc/woocommerce.php asks WooCommerce for. */
.pn-commerce .pn-wish__table td.product-thumbnail {
	width: 112px;
	padding-right: var(--space-5);
}
.pn-commerce .pn-wish__table td.product-thumbnail img {
	display: block;
	width: 88px;
	max-width: 88px;
	height: 110px;
	object-fit: cover;
}

/* The head cell over the picture carries only a screen-reader label, so it
   would otherwise be a hairline over nothing 112px wide. */
.pn-commerce .pn-wish__table th.product-thumbnail {
	width: 112px;
}

.pn-commerce .pn-wish__table td.product-name {
	font-size: var(--text-body);
	line-height: var(--lh-body);
	color: var(--text-primary);
}

.pn-commerce .pn-wish__table td.product-price {
	color: var(--text-secondary);
}

/* WooCommerce's own word for the state, in the theme's caption register. The
   class it sets is the signal — `out-of-stock` is the only one that has to
   look different, and it is the only one that says no. */
.pn-commerce .pn-wish__stock {
	display: inline;
	margin: 0;
	padding: 0;
	font-size: var(--text-small);
	line-height: var(--lh-small);
	font-weight: var(--weight-regular);
	color: var(--text-secondary);
}
.pn-commerce .pn-wish__stock.out-of-stock {
	color: var(--error);
}

/* The two actions sit at the end of the row, and neither is a block of colour.
   購物車 is one page with one filled button on it — 前往結帳 — and a list of six
   saved products should not carry six more. */
.pn-commerce .pn-wish__table :is(td, th):is(.product-action, .product-remove) {
	width: 44px;
	padding-right: 0;
	text-align: right;
}

/* 加入購物車, as the listing card draws it: 44px, borderless, ink, green under
   the pointer. Restated rather than shared — `.pn-lcard__add` lives in
   listing.css, which is not loaded on this page — and the values are that
   rule's own.

   The scope is carried three classes deep because of what it has to beat. The
   button rule at the top of this file is
   `.pn-commerce .pn-page__body :is(…, button[type="submit"]):not(.is-link)`,
   and `:is()` takes the specificity of its heaviest argument — which is
   `button[type="submit"]`, a type *and* an attribute. So that rule is 0-4-1,
   not the 0-4-0 it looks like, and a four-class rule of ours loses to it by
   one element. Measured before it was believed: the button came out
   `rgb(47, 74, 58)` and 50px wide, which is the filled brand block. */
.pn-commerce .pn-page__body .pn-wish__table .pn-wish__add:not(.is-link) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 44px;
	height: 44px;
	min-height: 0;
	padding: 0;
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	color: var(--text-primary);
	cursor: pointer;
	transition:
		color var(--dur-fast) var(--ease-out),
		transform var(--dur-fast) var(--ease-out);
}
.pn-commerce .pn-page__body .pn-wish__table .pn-wish__add:not(.is-link):hover {
	background: none;
	color: var(--text-link);
}
.pn-commerce .pn-wish__add:active {
	transform: scale(var(--press-scale));
}
.pn-commerce .pn-wish__add .pn-icon {
	color: currentColor;
}

/* The ×, which is the bag sheet's — same glyph, same 44px target, same two
   colours. It is a `<button type="submit">`, so it starts as the filled brand
   button and has to be taken back to nothing at the same weight as the add. */
.pn-commerce .pn-page__body .pn-wish__table .pn-wish__remove:not(.is-link) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	min-height: 0;
	padding: 0;
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	color: var(--text-tertiary);
	font-family: var(--font-sans);
	font-size: var(--text-body);
	line-height: 1;
	cursor: pointer;
	transition: color var(--dur-fast) var(--ease-out);
}
.pn-commerce .pn-page__body .pn-wish__table .pn-wish__remove:not(.is-link):hover {
	background: none;
	color: var(--text-primary);
}

.pn-commerce .pn-wish__table td.product-cb,
.pn-commerce .pn-wish__table th.product-cb {
	width: 28px;
	padding-right: var(--space-3);
}
.pn-commerce .pn-wish__table .input-checkbox {
	width: auto;
	min-height: 0;
	margin: 0;
}

/* The foot holds the bulk-action row and the nonce. It is not a row of the
   record, so it carries no hairline — the last product's own is the end of the
   table — and the plugin's script hides it outright when there is nothing in
   it but the hidden field. */
.pn-commerce .pn-wish__table tfoot td {
	padding: var(--space-5) 0 0;
	border: 0;
}

.pn-commerce .pn-wish__nav:not(:empty) {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-4);
	margin-top: var(--space-6);
}

/* ── The table on a phone ─────────────────────────────────────────────── */

@media (max-width: 767.98px) {
	/* One block per saved product, from the shared `shop_table_responsive`
	   rules above — with two corrections, because a product row has a picture
	   in it and a heading, and an orders row has neither.

	   `.woocommerce` is carried in the scope of both, and not for tidiness: the
	   shared rule is `.pn-commerce .woocommerce table.shop_table_responsive
	   :is(th, td)`, which is 0-3-2, and without it these are 0-3-1 — one
	   element short, so they lost and the picture sat on the right of an empty
	   label. Measured: `display` came back `flex`. */

	/* The picture is not a label and a value, so it does not become one: it
	   sits at the left with the block's own top padding above it. */
	.pn-commerce .woocommerce .pn-wish__table td.product-thumbnail {
		display: block;
		width: auto;
		padding: var(--space-4) 0 var(--space-3);
	}
	.pn-commerce .woocommerce .pn-wish__table td.product-thumbnail::before {
		content: none;
	}
	/* Measured at x 143.5 in a 327 block — centred. The cascade under this one
	   gives a block image automatic inline margins, which a `text-align` on the
	   cell cannot undo because a block does not answer to it. */
	.pn-commerce .woocommerce .pn-wish__table td.product-thumbnail img {
		margin-inline: 0;
	}

	/* The name is the block's heading, so it leads rather than sitting on the
	   right of its own label. */
	.pn-commerce .woocommerce .pn-wish__table td.product-name {
		display: block;
		padding-bottom: var(--space-3);
		text-align: left;
	}
	.pn-commerce .woocommerce .pn-wish__table td.product-name::before {
		content: none;
	}

	/* Both actions keep their label on the left and their 44px target on the
	   right, which is what the shared rule already does — they only need the
	   width taken off, because a block is as wide as the page. */
	.pn-commerce .woocommerce .pn-wish__table :is(td, th):is(.product-action, .product-remove) {
		width: auto;
	}
}
