/* ============================================================================
   Account surface — the storefront's ink/ivory/gold system, kept deliberately
   quiet.

   Phase 5.2 moved this out of the inline <style> block that account.html used
   to carry, so every account section shares one stylesheet and so the shell's
   states, navigation and responsive rules have somewhere to live. The first
   block below is the Phase 5.1 styling verbatim; nothing about the signed-off
   appearance was re-designed, only relocated.
   ========================================================================= */

/* ---- Phase 5.1 account surface (verbatim) --------------------------------- */
.account-page { max-width: 1100px; margin: 0 auto; padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.25rem, 5vw, 5rem) clamp(3rem, 7vw, 6rem); }
.account-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1.5rem; padding-bottom: 1.75rem; border-bottom: 1px solid var(--line); }
.account-title { margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(2rem, 5vw, 3rem); line-height: 1.05; }
.account-sub { margin: .75rem 0 0; max-width: 46ch; color: var(--muted); font-size: .9rem; line-height: 1.7; }

.btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 1.35rem; border: 1px solid var(--line); background: none; color: var(--ivory); font: 500 .72rem/1 var(--sans); letter-spacing: .16em; text-transform: uppercase; cursor: pointer; transition: border-color .3s ease, color .3s ease, background .3s ease; }
/* Hover is guarded exactly as it is in the storefront stylesheets: a tap on a
   touch screen latches `:hover` and the colour then stays applied. The press
   gets its own state so the button still answers immediately. */
.btn:active { border-color: var(--gold); color: var(--gold); }
.btn-destructive:active { border-color: #b4544a; color: #b4544a; }
@media (hover: hover) {
  .btn:hover { border-color: var(--gold); color: var(--gold); }
  .btn-destructive:hover { border-color: #b4544a; color: #b4544a; }
}
.btn:disabled { opacity: .5; cursor: not-allowed; }

.account-section { border: 1px solid var(--line); background: var(--ink-soft); padding: clamp(1.4rem, 3vw, 2.25rem); }
.account-section + .account-section { margin-top: 1.5rem; }
.section-title { margin: 0 0 1.6rem; font-family: var(--display); font-weight: 400; font-size: clamp(1.15rem, 2.4vw, 1.5rem); }

.profile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1.6rem 2rem; }
.profile-field { display: grid; gap: .45rem; min-width: 0; }
.profile-label { color: var(--muted); font-size: .66rem; letter-spacing: .2em; text-transform: uppercase; }
.profile-value { color: var(--ivory); font-size: .95rem; overflow-wrap: anywhere; }
.profile-value.empty { color: var(--muted); font-style: italic; }

.alert { margin: 1.75rem 0 0; padding: .9rem 1.1rem; border: 1px solid var(--line); border-left: 2px solid var(--muted); background: var(--ink-soft); color: var(--ivory); font-size: .84rem; line-height: 1.6; }
.alert-success { border-left-color: var(--gold); }
.alert-error { border-left-color: #b4544a; }
.alert-info { border-left-color: var(--muted); }

/* ---- Shell layout ---------------------------------------------------------
   The header keeps the rule the signed-off page had underneath it. It used to
   be `.account-page > .account-section { margin-top: … }`; the section now sits
   inside the layout wrapper, so the same distance moved onto the wrapper and
   the rendered result is unchanged. */
.account-layout { margin-top: clamp(2rem, 4vw, 3rem); }

/* Two columns only when a navigation rail actually rendered. Phase 5.3 is the
   first phase with two enabled sections, so this is the rule that engages for
   real; a page with a single enabled section still has no `.account-nav` and
   keeps the single-column composition Phase 5.1 was signed off with. */
@media (min-width: 981px) {
  .account-layout:has(> [data-account-nav] > .account-nav) { display: grid; grid-template-columns: minmax(180px, 220px) minmax(0, 1fr); gap: clamp(1.5rem, 3vw, 2.75rem); align-items: start; }
  /* The grid gap already separates the rail from the content, so the rail's own
     bottom margin would double it. */
  .account-layout:has(> [data-account-nav] > .account-nav) > [data-account-nav] > .account-nav { margin-bottom: 0; }
}

/* ---- Account navigation ---------------------------------------------------
   Rendered only at two or more enabled sections (see account-shell.mjs). Both
   compositions shipped in Phase 5.2 and were exercised against a synthetic
   two-section registry; Phase 5.3 enabling Profile is what put them on a real
   page rather than a test. */
.account-nav { margin-bottom: clamp(1.5rem, 3vw, 2rem); }
.account-nav ul { display: grid; margin: 0; padding: 0; list-style: none; }
.account-nav a { display: flex; align-items: center; min-height: 44px; padding: .35rem 0; border-bottom: 1px solid var(--line); color: var(--muted); font-size: .88rem; text-decoration: none; transition: color .3s ease; }
.account-nav a[aria-current="page"] { color: var(--gold); }
.account-nav a:active { color: var(--ivory); }
@media (hover: hover) {
  .account-nav a:hover { color: var(--ivory); }
}
.account-nav a:focus-visible { color: var(--ivory); outline: 2px solid var(--gold); outline-offset: 4px; }

/* Narrow screens read the same navigation as a single scrollable row under the
   identity header, so the content keeps the full width. */
@media (max-width: 980px) {
  .account-nav ul { display: flex; flex-wrap: nowrap; gap: 0 1.35rem; overflow-x: auto; scrollbar-width: thin; }
  .account-nav li { flex: 0 0 auto; }
  .account-nav a { border-bottom: 0; white-space: nowrap; }
}

/* ---- Profile form ---------------------------------------------------------
   Account-scoped names rather than the auth pages' .form-* ones. The auth pages
   are a light card and load customer-auth.css; this surface is dark and loads
   account.css; the two stylesheets never co-load. Reusing a .form-* name here
   would leave one class meaning opposite things depending on the page — a trap
   for whoever next loads both. */

.account-form { display: grid; gap: 1.75rem; }
.account-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1.4rem 2rem; }
.account-field { display: grid; gap: .45rem; min-width: 0; }
/* Email is read-only and has no control to sit beside, so it takes the row. */
.account-field--wide { grid-column: 1 / -1; }
.account-label { color: var(--muted); font-size: .66rem; letter-spacing: .2em; text-transform: uppercase; }

.account-input { width: 100%; min-height: 44px; padding: .75rem .85rem; border: 1px solid var(--line); background: var(--ink); color: var(--ivory); font: 400 .95rem/1.4 var(--sans);
  /* Declares the surface this control sits on, so the browser draws its own
     date-picker indicator and calendar for a dark background instead of a
     light one. */
  color-scheme: dark; transition: border-color .3s ease; }
.account-input:focus-visible { border-color: var(--gold); outline: 2px solid var(--gold); outline-offset: 2px; }
.account-input[aria-invalid="true"] { border-color: #b4544a; }

/* A lighter tint of the destructive red: #b4544a is tuned for a border against
   the dark surface and does not carry enough contrast as body text. */
.account-field-error { margin: 0; color: #d98b82; font-size: .78rem; line-height: 1.5; }
.account-static { margin: 0; color: var(--ivory); font-size: .95rem; overflow-wrap: anywhere; }
.account-note { margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.6; }

.account-form-actions { display: flex; flex-wrap: wrap; gap: .75rem; }
/* The status line reserves its height so a save confirmation does not shift the
   buttons above it the moment it appears. */
.account-form-status { margin: 0; min-height: 1.2em; color: var(--muted); font-size: .84rem; line-height: 1.6; }
.account-form-status.is-success { color: var(--gold); }
.account-form-status.is-error { color: #d98b82; }
.account-form-status:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* ---- Shell states ---------------------------------------------------------
   Loading is a real state, not a grid of placeholder dashes: an empty-looking
   profile reads as a finished page that lost its data. */
.account-loading { display: flex; align-items: center; gap: .7rem; margin: 0; color: var(--muted); font-size: .9rem; }
.account-loading::before { content: ""; flex: 0 0 13px; width: 13px; height: 13px; border: 1px solid var(--line); border-top-color: var(--gold); border-radius: 50%; animation: account-spin 1s linear infinite; }
@keyframes account-spin { to { transform: rotate(360deg); } }

/* The storefront's global reduced-motion rule already zeroes this; repeating it
   here keeps this stylesheet correct on its own terms rather than by dependency. */
@media (prefers-reduced-motion: reduce) {
  .account-loading::before { animation: none; }
}

/* The alert carries an optional recovery action for the session-expired and
   error states. */
.alert-text { margin: 0; }
.alert-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .9rem; }
.alert-actions .btn { text-decoration: none; }

@media (forced-colors: active) {
  .btn, .account-section, .alert, .account-nav a, .account-input { border: 1px solid ButtonText; }
  :focus-visible { outline: 2px solid Highlight; outline-offset: 4px; }
  .account-loading::before { border-top-color: Highlight; }
}

/* ============================================================================
   Phase 5.4 — the address book.

   Cards above, one form below. Every colour, border and rule here is one the
   storefront already uses: this section introduces no new visual vocabulary,
   it only reuses --line, --ink, --ink-soft, --ivory, --muted and --gold so the
   page reads as the same account as Overview and Profile.
   ========================================================================= */

.address-list { display: grid; gap: 1rem; margin: 0 0 2.25rem; padding: 0; list-style: none; }
.address-list[hidden] { display: none; }

.address-card { display: grid; gap: .85rem; padding: 1.15rem 1.25rem; border: 1px solid var(--line); background: var(--ink); }
/* The default is the one a checkout will preselect, so it is the one card that
   looks different. A left rule rather than a fill, to stay inside the palette
   the rest of the account uses. */
.address-card[data-default] { border-left: 2px solid var(--gold); }

.address-card-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .6rem .75rem; }
.address-card-title { margin: 0; font-family: var(--display); font-weight: 400; font-size: 1.05rem; line-height: 1.3; }
.address-badge { padding: .2rem .5rem; border: 1px solid var(--gold); color: var(--gold); font: 500 .58rem/1 var(--sans); letter-spacing: .18em; text-transform: uppercase; }

/* An <address> element, so the semantics are the browser's. `font-style: normal`
   is the only override: italic is the element's typographic default, not
   something the storefront chose, and the storefront sets addresses in its
   body face like everything else. */
.address-card-lines { display: grid; gap: .18rem; margin: 0; font-style: normal; color: var(--ivory); font-size: .92rem; line-height: 1.55; overflow-wrap: anywhere; }

.address-card-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
/* Row gaps, not column gaps, so the three controls wrap to a second line rather
   than crowding on one. The gap is .6rem because .75rem reads as disconnected
   at this control size. */
.address-card-actions .btn { min-height: 38px; padding: 0 .95rem; font-size: .64rem; }
/* Same 44px target as everything else on the storefront — reduced only in the
   horizontal padding, never in the touch height. */
@media (hover: none) { .address-card-actions .btn { min-height: 44px; } }

.address-card-confirm { display: grid; gap: .7rem; padding: .85rem .95rem; border: 1px solid #b4544a; background: var(--ink-soft); }
.address-card-confirm[hidden] { display: none; }
.address-card-confirm-text { margin: 0; color: var(--ivory); font-size: .82rem; line-height: 1.6; }
.address-card-confirm-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.address-card-confirm-actions .btn { min-height: 38px; padding: 0 .95rem; font-size: .64rem; }
@media (hover: none) { .address-card-confirm-actions .btn { min-height: 44px; } }

/* The form is a peer of the list, separated by a rule rather than a card, so the
   page reads as "your addresses, then add another" instead of two equal
   objects fighting for the same attention. */
.address-form { margin: 0; padding-top: 2.25rem; border-top: 1px solid var(--line); }
.address-form[hidden] { display: none; }
.address-form-title { margin: 0; font-family: var(--display); font-weight: 400; font-size: 1.05rem; }

/* Phase 5.8 — the "Sign-in methods" block, and the account-page half of the
   provider buttons.
   -------------------------------------------------------------------------
   customer-auth.css carries the other half, for the sign-in and sign-up pages.
   Neither stylesheet can import the other and the two sets of pages share no
   stylesheet, so the icon sizing is repeated rather than shared — the same
   arrangement .btn already has in both files. It has to be repeated: an inline
   SVG with no width or height renders at the browser's 300x150 default, which
   would be a large empty box where a small mark belongs.

   Separated by a rule rather than nested in a second card, so the panel reads as
   "your details, then how you sign in" — a peer, not a competing object. */
.oauth-link-section { margin: 0; padding-top: 2.25rem; border-top: 1px solid var(--line); }
.oauth-link-section[hidden] { display: none; }
.oauth-link-title { margin: 0; font-family: var(--display); font-weight: 400; font-size: 1.05rem; }
/* justify-items, so the buttons keep their own width. Grid's default stretch
   would make every one of them full-bleed, which at this size reads as the
   panel's primary action — the opposite of what a secondary control should say. */
.oauth-link-list { display: grid; gap: .7rem; justify-items: start; margin-top: 1.1rem; }
/* The provider buttons live in their own grid inside the block, so that a
   re-render of the button list cannot take the "sign-in methods" line with it. */
.oauth-link-methods { display: grid; gap: .7rem; justify-items: start; }
.oauth-link-methods[hidden] { display: none; }
.oauth-link-list .btn { gap: .6rem; }
.provider-mark { width: 16px; height: 16px; flex: 0 0 16px; }

/* One row per way into the account. Three columns so the names line up down the
   block whatever each row's action is, and the state sits next to the thing it
   describes rather than at the end of a long line. */
.oauth-link-rows { display: grid; gap: .55rem; margin-top: 1.1rem; }
.method-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: .35rem .9rem;
  align-items: center;
  padding: .7rem .85rem;
  border: 1px solid var(--line);
  border-radius: 2px;
}
.method-row__name { font-size: .95rem; }
.method-row__state { color: var(--muted); font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; }
/* The action spans both columns, so a long "last method" sentence wraps under the
   name rather than squeezing the state label. */
.method-row__action { grid-column: 1 / -1; display: grid; justify-items: start; }
.method-row__why { color: var(--muted); font-size: .85rem; }
/* A disconnect is the one control here that takes something away, so it is drawn
   as an outline rather than filled — the same weight as a Connect, not more. */
.method-row__disconnect { gap: .6rem; }

@media (max-width: 480px) {
  .method-row { grid-template-columns: minmax(0, 1fr); }
  .method-row__state { justify-self: start; }
}

.account-textarea { min-height: 5.5rem; resize: vertical; }

@media (max-width: 480px) {
  /* Below this the three card controls cannot share a line without their
     labels truncating, so they go full width. Left-aligned rather than
     stretched: a full-width "Edit" reads as the card's only action. */
  .address-card-actions { display: grid; grid-template-columns: 1fr; }
  .address-card-actions .btn { justify-content: flex-start; }
  .address-card-confirm-actions { display: grid; grid-template-columns: 1fr; }
  .address-card-confirm-actions .btn { justify-content: flex-start; }
}

@media (forced-colors: active) {
  .address-card, .address-card-confirm, .address-badge { border: 1px solid ButtonText; }
  .address-card[data-default] { border-left: 3px solid Highlight; }
  .address-badge { color: Highlight; }
  /* A method row is a bordered box, so its border has to survive the palette
     swap or the list reads as loose lines of text. */
  .method-row { border: 1px solid ButtonText; }
}

/* ===========================================================================
   Phase 5.5 — Wishlist
   ---------------------------------------------------------------------------
   Rows, not cards. A wishlist holds up to 200 pieces and the things a customer
   does with a saved list are scan-for-one-thing and remove-one-thing, so the
   layout is a compact row with the controls at a predictable place on the
   right, the way a bag line is, rather than a card per piece.

   As in 5.4, this section introduces no new colour: --line, --ink, --ink-soft,
   --ivory, --muted and --gold are the whole palette, so the page reads as the
   same account as Overview, Profile and Addresses.
   ========================================================================= */

.wishlist-list { display: grid; gap: .75rem; margin: 1.5rem 0 0; padding: 0; list-style: none; }
.wishlist-list:empty { margin: 0; }

.wishlist-row { display: grid; grid-template-columns: 72px 1fr auto; align-items: center; gap: 1rem; padding: .85rem 1rem; border: 1px solid var(--line); background: var(--ink); }
/* A piece the catalogue no longer carries. Marked with a left rule in the
   error red and no longer in the body face, so the difference is legible
   without reading the note under it — somebody scanning for the piece they
   want must not have to read every reason to find the ones still buyable. */
.wishlist-row--unavailable { border-left: 2px solid #b4544a; }

/* A fixed square, so a row with a photograph and a row without one are the same
   height and the list does not step as products resolve. The empty variant is
   drawn rather than left as a broken image, which is the one thing that would
   look worse than no picture. */
.wishlist-thumb { width: 72px; height: 72px; object-fit: cover; background: var(--ink-soft); }
.wishlist-thumb--empty { background: var(--ink-soft); border: 1px solid var(--line); }

.wishlist-row-body { display: grid; gap: .3rem; min-width: 0; }
.wishlist-row-name { margin: 0; font-size: .95rem; line-height: 1.4; overflow-wrap: anywhere; }
.wishlist-row-name a { color: var(--ivory); text-decoration: none; }
/* :hover is guarded and :active is not, and that split is the whole point. A tap
   sets :active, so the gold is the touch feedback on a device with no hover at
   all — it is the only affordance a finger gets. An unguarded :hover would be
   the *extra* one: it latches after the finger leaves and colours a link the
   customer is no longer touching. */
@media (hover: hover) {
  .wishlist-row-name a:hover { color: var(--gold); }
}
.wishlist-row-name a:active { color: var(--gold); }
.wishlist-row-name a:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
/* An unavailable row has no link, and its name is a statement rather than a
   heading, so it is dimmed to match. */
.wishlist-row--unavailable .wishlist-row-name { color: var(--muted); font-style: italic; }
.wishlist-row-price { margin: 0; color: var(--muted); font-size: .82rem; }
.wishlist-row-reason { margin: 0; color: #d98b82; font-size: .76rem; line-height: 1.5; }

.wishlist-row-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.wishlist-row-actions .btn { min-height: 38px; padding: 0 .95rem; font-size: .64rem; text-decoration: none; }
@media (hover: none) { .wishlist-row-actions .btn { min-height: 44px; } }

/* The count sits under the heading, not in the shell's alert region: the shell
   clears its own alert on every re-render, so a count parked there would
   disappear the moment the list refreshed. */
[data-wishlist-count] { margin: 0 0 .25rem; color: var(--muted); font-size: .78rem; }
[data-wishlist-status] { margin: .9rem 0 0; min-height: 1.2em; color: var(--muted); font-size: .84rem; line-height: 1.6; }
[data-wishlist-status].is-success { color: var(--gold); }
[data-wishlist-status].is-error { color: #d98b82; }

@media (max-width: 560px) {
  /* Three columns cannot hold a title, a price and two controls on a phone.
     The thumbnail drops first because it is the only part that is redundant
     with the name, and the controls go to their own full-width line so a
     thumb-reach at the bottom of a long list does not mean reaching across
     the screen. */
  .wishlist-row { grid-template-columns: 56px 1fr; align-items: start; gap: .8rem; }
  .wishlist-thumb { width: 56px; height: 56px; }
  .wishlist-row-actions { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr; }
  .wishlist-row-actions .btn { justify-content: flex-start; }
}

@media (forced-colors: active) {
  .wishlist-row, .wishlist-thumb--empty { border: 1px solid ButtonText; }
  .wishlist-row--unavailable { border-left: 3px solid Highlight; }
  .wishlist-row-price, .wishlist-row-reason { color: ButtonText; }
}
