/* buy.css — /buy, the configurator, on the company design system.
 *
 * The page itself carries no comment: apps/comsite/build.sh publishes it, and that build
 * refuses an HTML comment in a released byte (a template's source notes and a tool's markers
 * look the same from the outside). So what /buy is, is written here, beside it.
 *
 * hoopgram.com/buy is the configurator (S4, owner directive 2026-08-24T16Z §S4). Seven steps,
 * apple.com's Buy MacBook Pro rhythm: one screen, a running price, cards, dots you can jump
 * with. No price is ever hand-written there — every number comes from window.HoopPricing,
 * which renders "price being announced" while pricing.json says confirmed:false (17Z). Zero
 * npm, zero inline style, zero dark pattern: every default is the cheapest/most conservative
 * choice, no countdown, no "N left", no pre-checked add-on. The header is /site-chrome.js —
 * the same navigation, from the same apps/comsite/components/site-chrome.json, that the
 * company site renders at build time and Forge mounts at request time.
 *
 * What changed and why: until now this page was the last representative surface still dressed
 * by apex.css — its own eight-colour palette, its own type scale, its own button. Two stylesheets
 * describing one company is one stylesheet plus a future disagreement, and this page is where a
 * disagreement costs the most: it is the screen a stranger is on when they decide to pay.
 *
 * The rules this sheet keeps are site.css's rules, not new ones:
 *   1. Colour has one source. Every colour below is a /tokens.css name. This sheet invents none,
 *      and writes no literal — which is also what lets the page follow light, dark and the OS
 *      without a second palette (tokens.css carries all four states).
 *   2. Type has one ladder. Sizes are --step-* rungs from site.css. The configurator's own
 *      controls sit on --step-meta/--step-body deliberately: a card label is not a heading.
 *   3. Space has one rhythm: --sp-* and site.css's --space-*.
 *   4. A component is defined once. Anything site.css already owns — .ui-shell, .skip, .ui-button,
 *      .ui-eyebrow, .ui-summary, .presence-shot — is used, not re-cut. What is left here is the
 *      configurator itself, which no other page has.
 *
 * Loaded after /site.css by apex/buy.html. The header comes from /site-chrome.js (the shared
 * navigation every surface renders from apps/comsite/components/site-chrome.json); the footer is
 * still apex.js's, so its chrome is re-dressed at the bottom of this file rather than left bare.
 */

/* -- the running price bar -- */
.buy-pricebar{position:sticky; top:0; z-index:9; background:var(--glass-bg); -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur); border-bottom:1px solid var(--line)}
.buy-pricebar-in{display:flex; gap:var(--sp-5); flex-wrap:wrap; align-items:center; min-block-size:var(--tap); font-size:var(--step-meta)}
.buy-pricebar-item b{font-weight:500; color:var(--dim); margin-inline-end:var(--sp-1)}
@media (prefers-reduced-transparency:reduce){.buy-pricebar{background:var(--surface); -webkit-backdrop-filter:none; backdrop-filter:none}}

/* -- the opening --
   site.css opens every page with --section-y, which is right for a document and wrong here: the
   price bar is already a band across the top, so the two paddings stacked into ~190px of empty
   cream before the first word. The hero keeps its own rhythm instead. */
main{padding-block:0}
.buy-hero{padding-block:clamp(40px,7vh,72px) clamp(28px,5vh,48px); text-align:start}
.buy-hero h1{margin-top:var(--sp-3)}
.buy-hero .ui-summary{max-width:44ch}

/* -- the two columns: a picture that stays, a form that scrolls -- */
.buy-wrap{display:grid; grid-template-columns:minmax(0,44%) minmax(0,1fr); gap:var(--sp-7); align-items:start; padding-bottom:var(--space-5)}
.buy-visual{position:sticky; top:var(--space-6)}
.buy-visual .presence-shot{margin:0}
.buy-steps{display:grid; grid-template-columns:minmax(0,1fr); gap:var(--sp-7)}

/* -- one step -- */
.buy-step{min-inline-size:0; border:1px solid var(--line); border-radius:var(--r-2xl); background:var(--paper); padding:var(--card-pad); box-shadow:var(--shadow-1); scroll-margin-top:150px; text-align:start}
.buy-step h2{font-size:var(--step-block); margin-top:var(--sp-1); max-width:none}
.buy-review h2{font-size:var(--step-section)}

/* -- one choice --
   A card here is a control, not site.css's .ui-card: it is pressable, it carries an aria-pressed
   state, and a whole grid of them must stay scannable at 13rem wide. It borrows the card's
   surface, border and radius rather than declaring a second look. */
.buy-cards{display:grid; grid-template-columns:repeat(auto-fit,minmax(13rem,1fr)); gap:var(--sp-3); margin-top:var(--sp-5)}
.buy-card{display:flex; flex-direction:column; align-items:flex-start; gap:var(--sp-1); text-align:start; border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface); padding:var(--sp-4) var(--sp-4); cursor:pointer; font:inherit; color:var(--fg); inline-size:100%; transition:border-color var(--motion-base) var(--ease-emphasized)}
.buy-card:hover{border-color:var(--brand-ink)}
.buy-card.on{border-color:var(--brand-ink); box-shadow:0 0 0 3px var(--ring)}
.buy-card[disabled]{cursor:not-allowed; opacity:.58}
.buy-card[disabled]:hover{border-color:var(--line)}
.buy-card:focus-visible{outline:2px solid var(--brand-ink); outline-offset:3px}
.buy-card b{font-weight:500; font-size:var(--step-body)}
.buy-card span{color:var(--dim); font-size:var(--step-meta); line-height:1.5}
.buy-card .buy-price{margin-top:var(--sp-1); font-weight:500; color:var(--brand-ink); font-size:var(--step-meta)}
.buy-note{color:var(--dim); font-size:var(--step-meta); margin-top:var(--sp-3); max-width:46rem}
.buy-note a{color:var(--brand-ink)}
.buy-gpu-detail{margin-top:var(--sp-4); display:grid; gap:var(--sp-2)}
.buy-gpu-card{display:flex; justify-content:space-between; gap:var(--sp-3); border:1px solid var(--line); border-radius:var(--r-md); padding:var(--sp-2) var(--sp-3); font-size:var(--step-meta); background:var(--surface)}
.buy-gpu-card b{font-weight:500}
.buy-gpu-meta{color:var(--dim); font-size:var(--step-fine); margin-top:var(--sp-2)}
.buy-pay-card{margin-top:var(--sp-4); border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface); padding:var(--sp-4)}
.buy-pay-card b{font-size:var(--step-body); font-weight:500}

/* -- naming the machine -- */
.buy-name{margin-top:var(--sp-5)}
.buy-name label{display:block; font-size:var(--step-meta); color:var(--dim); margin-bottom:var(--sp-1)}
.buy-name-row{display:flex; align-items:center; gap:var(--sp-2); max-width:26rem; flex-wrap:wrap}
/* 16px is not a size choice: below it iOS Safari zooms the whole page on focus. */
.buy-name-row input{flex:1; min-inline-size:8rem; font:inherit; font-size:16px; padding:11px var(--sp-3); border:1px solid var(--line); border-radius:var(--r-md); background:var(--paper); color:var(--fg); outline:none}
.buy-name-row input:focus{border-color:var(--brand-ink); box-shadow:0 0 0 4px var(--ring)}
.buy-name-suffix{color:var(--dim); font-size:var(--step-meta); white-space:nowrap}
.buy-name-status{margin-top:var(--sp-2); font-size:var(--step-meta); color:var(--dim); min-block-size:1.4em}
.buy-name-status.ok{color:var(--brand-ink)}

/* -- what you are about to pay for -- */
.buy-summary{display:grid; grid-template-columns:auto 1fr; gap:var(--sp-2) var(--sp-4); margin-top:var(--sp-5); font-size:var(--step-meta)}
.buy-summary dt{color:var(--dim)}
.buy-summary dd{margin:0; text-align:end}
.buy-total{display:grid; gap:var(--sp-1); margin-top:var(--sp-5); padding-top:var(--sp-4); border-top:1px solid var(--line); font-size:var(--step-body)}
.buy-total div{display:flex; justify-content:space-between; gap:var(--sp-3)}
.buy-total b{font-weight:500}
.buy-cta{margin-top:var(--sp-5); inline-size:100%}

/* -- where you are in the seven steps -- */
.buy-dots{position:fixed; inset-inline-end:var(--sp-5); top:50%; transform:translateY(-50%); display:flex; flex-direction:column; gap:var(--sp-2); z-index:8}
.buy-dot{inline-size:28px; block-size:28px; padding:0; border:0; background:none; cursor:pointer; display:grid; place-items:center}
.buy-dot::after{content:""; inline-size:9px; block-size:9px; border-radius:50%; background:var(--line-2); border:1px solid var(--line-2); display:block}
.buy-dot.on::after{background:var(--brand-ink); border-color:var(--brand-ink); inline-size:11px; block-size:11px}
.buy-mobilebar{display:none}

@media (max-width:760px){
  .buy-wrap{grid-template-columns:1fr; gap:var(--sp-6)}
  .buy-visual{display:none}
  .buy-dots{display:none}
  .buy-steps{padding-bottom:76px}
  .buy-mobilebar{display:flex; position:fixed; inset-inline:0; bottom:0; z-index:11; align-items:center; justify-content:space-between; gap:var(--sp-3);
    background:var(--glass-bg); -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur); border-top:1px solid var(--line);
    padding:var(--sp-3) var(--sp-4) calc(var(--sp-3) + env(safe-area-inset-bottom))}
  .buy-mobilebar span{font-size:var(--step-meta); font-weight:500}
  .buy-mobilebar button{font:inherit; font-size:var(--step-meta); font-weight:500; padding:var(--sp-2) var(--sp-5); min-block-size:var(--tap); border:0; border-radius:var(--r-pill); color:var(--bg); background:var(--fg); cursor:pointer}
  .buy-mobilebar button[disabled]{cursor:not-allowed; opacity:.48}
}
@media (prefers-reduced-motion:reduce){.buy-card{transition-duration:1ms}}

/* -- the foot --
   apex.js still renders this page's footer (the language picker and the appearance control live
   in it, and both are real controls a buyer may need). Its markup is legacy; its dress is not —
   these rules put it on the same tokens as everything above, so removing apex.css costs the page
   nothing. When the shared footer lands, this whole block goes with it. */
footer{margin-top:clamp(40px,8vh,80px); border-top:1px solid var(--line); padding:var(--sp-7) 0 var(--space-5)}
footer .wrap{max-width:var(--page-max); margin:0 auto; padding:0 24px}
.engrave{text-align:center; color:var(--brand-ink); font-size:var(--step-lead)}
html[lang="zh-CN"] .engrave{letter-spacing:.5em; text-indent:.5em}
html[lang="en"] .engrave{font-family:var(--font-ui); font-size:var(--step-fine); letter-spacing:.24em; text-transform:uppercase; text-indent:.24em}
.theme-foot{display:flex; align-items:center; justify-content:center; gap:var(--sp-2); margin-top:var(--sp-6); color:var(--dim); font-size:var(--step-fine); flex-wrap:wrap}
.foot-sep{color:var(--dim)}
.foot{display:flex; flex-wrap:wrap; gap:var(--sp-2) var(--sp-5); justify-content:center; margin-top:var(--space-4); font-size:var(--step-meta); color:var(--dim)}
.foot a{display:inline-flex; align-items:center; justify-content:center; min-inline-size:var(--tap); min-block-size:var(--tap); margin-block:-10.5px; text-decoration:none}
.foot a:hover{color:var(--fg)}
.fine{text-align:center; color:var(--dim); font-size:var(--step-fine); margin-top:var(--sp-4)}
.seg{display:inline-flex; align-items:center; padding:2px; border:1px solid var(--line); border-radius:var(--r-pill); background:color-mix(in oklab,var(--paper) 76%,transparent)}
.seg button{position:relative; isolation:isolate; border:0; background:none; color:var(--dim); font:inherit; font-size:var(--step-fine); line-height:1; cursor:pointer; min-inline-size:var(--tap); block-size:var(--tap); margin-block:-9px; padding:0 9px; border-radius:var(--r-pill); white-space:nowrap}
.seg button::before{content:""; position:absolute; z-index:-1; inset:9px 0; border-radius:var(--r-pill)}
.seg button:hover{color:var(--fg)}
.seg button.on{background:none; color:var(--bg)}
.seg button.on::before{background:var(--fg)}
.lang-pick{position:relative; display:inline-block}
.lang-pick > button{position:relative; isolation:isolate; display:inline-flex; align-items:center; gap:var(--sp-1); border:0; min-block-size:var(--tap); margin-block:-4.5px; border-radius:var(--r-pill); background:transparent; color:var(--dim); font-size:var(--step-fine); padding:var(--sp-1) 13px; cursor:pointer}
.lang-pick > button::before{content:""; position:absolute; z-index:-1; inset:4.5px 0; border:1px solid var(--line); border-radius:var(--r-pill)}
.lang-pick > button:hover{color:var(--fg)}
.lang-pick > button i{font-style:normal; transform:rotate(90deg); display:inline-block; line-height:1}
.lang-pick-menu{position:absolute; inset-block-end:calc(100% + var(--sp-2)); inset-inline-start:0; min-inline-size:9rem; background:var(--paper); border:1px solid var(--line); border-radius:var(--r-md); box-shadow:var(--shadow-pop); padding:var(--sp-1); display:grid; z-index:60}
/* An explicit display rule beats the [hidden] UA default — restate it, or the menu never closes. */
.lang-pick-menu[hidden]{display:none}
.lang-pick-menu button{border:0; background:transparent; color:var(--fg); text-align:start; font-size:var(--step-meta); padding:7px var(--sp-2); border-radius:var(--r-sm); cursor:pointer}
.lang-pick-menu button:hover{background:var(--brand-soft)}
/* The authenticated invitation handoff reuses the Forge gift controller on /buy. */
.gift-main-hidden,.gift-main-hidden + #gift-panel + .buy-dots,.gift-main-hidden ~ .buy-dots,.gift-main-hidden ~ .buy-mobilebar{display:none!important}
.gift-panel{max-width:30rem;margin:0 auto;padding:var(--sp-4) var(--sp-4)}
