/* ===========================================================================
 * BuyShip.jp - default.css  (core + desktop, mobile-first)
 * ---------------------------------------------------------------------------
 * Theme colours come from CSS custom properties injected per-company by
 * App\Core\Theme::cssVariables(). Never hard-code brand colours here.
 * Pair with mobile.css for small-screen behaviour (bottom nav etc.).
 * =========================================================================== */

:root {
  --primary-color: #1f6feb;
  --secondary-color: #6c757d;
  --button-color: #1f6feb;
  --table-header-color: #f1f5f9;
  --background-color: #ffffff;
  --text-color: #111827;

  --muted: #6b7280;
  --border: #e5e7eb;
  --field-border: #c9d0d8;   /* slightly stronger so input outlines read clearly (Wise-style) */
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --app-bg: #f1f5f9;
  --radius: 16px;
  --radius-sm: 12px;
  --radius-pill: 100px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
  --sidebar-w: 248px;
  --topbar-h: 60px;

  --ok: #16a34a;
  --warn: #f59e0b;
  --danger: #dc2626;
  --info: #2563eb;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", "Hiragino Sans",
               "Noto Sans JP", "Helvetica Neue", Arial, sans-serif;
  color: var(--text-color);
  background: var(--app-bg);
  font-size: var(--base-font-size, 16px);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Per-language CJK faces. The default stack uses a Traditional-Chinese face,
   which mis-positions Japanese punctuation (。、 sit too high). Simplified
   Chinese pages use SC faces below.

   Japanese pages mirror Apple's JP typography: lead with the system font so
   Apple devices render San Francisco (SF Pro) for Latin and Hiragino Sans for
   Japanese — exactly like apple.com/jp. "SF Pro JP"/"SF Pro Text" pick up the
   real Apple faces where installed; Noto Sans JP is the clean cross-platform
   fallback for Windows/Android (Apple's own SF Pro JP webfont is proprietary
   and can't be self-hosted). Inter is intentionally NOT first here so Latin
   matches Apple's SF rather than overriding it. */
html[lang="ja"] body, html[lang="ja"] button,
html[lang="ja"] input, html[lang="ja"] select, html[lang="ja"] textarea {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro JP", "SF Pro Text",
    "SF Pro Display", "Hiragino Sans", "Hiragino Kaku Gothic ProN",
    "Noto Sans JP", "Noto Sans CJK JP", "Yu Gothic", "YuGothic", Meiryo,
    "Helvetica Neue", Arial, sans-serif;
  letter-spacing: .01em;
}
/* Chinese stacks put a Chinese face first so hanzi use the right regional glyph
   forms, then fall back to a Japanese face for KANA.
   This matters everywhere on this site, not just on Japanese pages: product
   names are copied from Japanese shops, so katakana (マフラー, バンパー) appears
   on quotations, warehouse lists and shipments in EVERY language. Microsoft
   YaHei and Noto Sans SC/TC contain no kana at all, so without a JP fallback a
   Windows visitor reading Chinese sees tofu boxes where the item name should be. */
html[lang="zh-Hans"] body, html[lang="zh-Hans"] button,
html[lang="zh-Hans"] input, html[lang="zh-Hans"] select, html[lang="zh-Hans"] textarea {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "PingFang SC", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC",
    "Hiragino Sans", "Noto Sans JP", "Yu Gothic", Meiryo,
    "Helvetica Neue", Arial, sans-serif;
}

html[lang="zh-Hant"] body, html[lang="zh-Hant"] button,
html[lang="zh-Hant"] input, html[lang="zh-Hant"] select, html[lang="zh-Hant"] textarea {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", "Noto Sans CJK TC",
    "Hiragino Sans", "Noto Sans JP", "Yu Gothic", Meiryo,
    "Helvetica Neue", Arial, sans-serif;
}

/* Links. Bare by default so dense UI (tables, toolbars, card chrome) stays clean and the
   row / card is the click affordance. When an underline does appear (hover, or always in
   running text below) it is thin and offset from the baseline, so it reads as a refined
   modern link rather than a 2005 hyperlink. */
a { color: var(--link-color, var(--primary-color)); text-decoration: none;
    text-underline-offset: 2px; text-decoration-thickness: 1px;
    transition: color .12s ease, text-decoration-color .12s ease; }
a:hover { text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 55%, transparent); }

/* Running text: links stay underlined ALWAYS. Inside a sentence, colour alone isn't a
   reliable "this is a link" signal (an accessibility gap for colour-blind readers, and it
   reads as plain text) — a persistent, low-contrast underline is the modern, accessible
   default. Structured UI (tables, buttons, nav, chips) keeps its own bare styling above. */
p a, li a, dd a, .form-hint a, .form-text a, .alert a, .prose a {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 30%, transparent);
}
p a:hover, li a:hover, dd a:hover, .form-hint a:hover, .form-text a:hover, .alert a:hover, .prose a:hover {
  text-decoration-color: currentColor;
}
h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.25; letter-spacing: -.01em; }
h1 { font-size: 1.9rem; font-weight: 800; }
h2 { font-size: 1.4rem; font-weight: 700; }
h3 { font-size: 1.15rem; font-weight: 700; }

/* ---- App shell ---------------------------------------------------------- */
.topbar {
  /* z-index must beat the mobile drawer (40) and its backdrop (35).
     `position: sticky` + z-index makes this element a STACKING CONTEXT, so
     anything inside it — the language dropdown, which asks for z-index 60 —
     is trapped beneath whatever the topbar itself scores. At 30 the drawer
     covered the open dropdown entirely: the menu was rendering, just behind
     the sidebar. The drawer starts below the topbar (top: var(--topbar-h)),
     so raising the bar above it costs nothing visually. Modals stay higher
     still at 100. */
  position: sticky; top: 0; z-index: 50;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: 12px;
  padding: 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.topbar .brand { display: flex; align-items: center; gap: 10px; font-weight: 700; color: var(--text-color); }
.topbar .brand img { height: 30px; width: auto; }
.topbar .brand .logo-mark {
  width: 32px; height: 32px; border-radius: 8px; color: #fff; background: var(--primary-color);
  display: flex; align-items: center; justify-content: center; font-weight: 800;
}
.topbar .spacer { flex: 1; }
.topbar .topbar-actions { display: flex; align-items: center; gap: 8px; }

/* Member ID chip (always-visible customer identifier, tap to copy). */
.member-id-chip { display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--primary-color) 35%, transparent);
  background: color-mix(in srgb, var(--primary-color) 8%, transparent);
  color: var(--text-color); border-radius: var(--radius-pill); padding: 5px 12px; font-size: 13px; line-height: 1; }
.member-id-chip strong { font-variant-numeric: tabular-nums; letter-spacing: .05em; }
.member-id-chip svg { width: 15px; height: 15px; color: var(--muted); }
/* An icon() SVG sat inline next to small link text (the helper ships SVGs with no
   width/height), matching the menu's icon style. */
.link-ic { display: inline-flex; align-items: center; gap: 4px; }
.link-ic svg { width: 15px; height: 15px; flex: 0 0 15px; }
.member-id-chip.copied { background: color-mix(in srgb, var(--ok, #16a34a) 16%, transparent); border-color: var(--ok, #16a34a); }
.member-id-chip.copied svg { color: var(--ok, #16a34a); }

/* Wallet chip (always-visible balance + one-tap deposit, customers only). */
.wallet-chip { display: inline-flex; align-items: stretch; line-height: 1; font-size: 13px;
  border: 1px solid color-mix(in srgb, var(--primary-color) 35%, transparent);
  background: color-mix(in srgb, var(--primary-color) 8%, transparent);
  border-radius: var(--radius-pill); overflow: hidden; }
.wallet-chip .wallet-amt { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px 5px 12px;
  color: var(--text-color); text-decoration: none; }
.wallet-chip .wallet-amt strong { font-variant-numeric: tabular-nums; }
.wallet-chip svg { width: 15px; height: 15px; color: var(--muted); }
.wallet-chip .wallet-add { display: inline-flex; align-items: center; justify-content: center; min-width: 28px;
  border-left: 1px solid color-mix(in srgb, var(--primary-color) 30%, transparent);
  color: var(--primary-color); font-weight: 700; font-size: 17px; text-decoration: none; }
.wallet-chip .wallet-add:hover { background: color-mix(in srgb, var(--primary-color) 16%, transparent); }
.wallet-chip.is-neg { border-color: color-mix(in srgb, #dc2626 45%, transparent); background: color-mix(in srgb, #dc2626 8%, transparent); }
.wallet-chip.is-neg .wallet-amt strong { color: #dc2626; }

.menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface); cursor: pointer; color: var(--text-color);
}

.app-body { display: flex; min-height: calc(100vh - var(--topbar-h)); }

.sidebar {
  width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
  background: var(--surface); border-right: 1px solid var(--border);
  padding: 14px 10px; overflow-y: auto;
}
.sidebar .nav-section { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); padding: 12px 12px 6px; }
.sidebar .nav-link {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  color: var(--text-color); font-weight: 500; margin-bottom: 2px;
}
.sidebar .nav-link:hover { background: var(--surface-2); text-decoration: none; }
.sidebar .nav-link.active { background: color-mix(in srgb, var(--primary-color) 12%, transparent); color: var(--primary-color); }
.sidebar .nav-link svg { width: 20px; height: 20px; flex: 0 0 20px; }

/* Red "pending jobs" count badge on nav items (e.g. withdrawals awaiting approval). */
.nav-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
  background: #dc2626; color: #fff; font-size: 11px; font-weight: 700; line-height: 1;
  border-radius: 999px; white-space: nowrap;
}
.sidebar .nav-link .nav-badge { margin-left: auto; }
.mobile-nav a { position: relative; }
.mobile-nav .nav-badge { position: absolute; top: 2px; left: 50%; margin-left: 3px; }

/* "View as customer" read-only preview banner. */
.impersonate-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: #b45309; color: #fff; padding: 8px 16px; font-size: 13px; font-weight: 600; }
.impersonate-bar .btn { background: #fff; color: #b45309; border: 0; flex: 0 0 auto; }
/* "Act as customer" — writes are live, so use a stronger red to set it apart. */
.impersonate-bar--acting { background: #b91c1c; }
.impersonate-bar--acting .btn { color: #b91c1c; }

.content { flex: 1; min-width: 0; padding: 24px; }
.content > .page-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
.content > .page-header h1 { font-size: 1.6rem; margin: 0; }

.container { max-width: 1100px; }

/* ---- Cards / grid ------------------------------------------------------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px;
}
/* General sibling combinator (~), not adjacent (+): the gap then survives ANY
   number of non-card elements between two stacked cards — e.g. the one or more
   behaviour <script> blocks a card carries (the forwarding page has two scripts
   between the customs editor and the Actions card). The first card in a stack has
   no preceding card sibling, so it correctly gets no top margin. */
.card ~ .card { margin-top: 16px; }
/* In a grid, spacing is the gap — drop the stacked-card margin so cards in a
   row stay top-aligned and stretch to equal height. (Equal specificity to the
   rule above but declared later, so it wins for direct grid children.) */
.grid > .card { margin-top: 0; }
.card { padding: 20px; }
.card .card-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; }
.grid { display: grid; gap: 16px; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
/* Detail pages (shipment, forwarding…): History stacks BELOW the cards at every
   width (it's reference info), so the operational column — and wide tables like the
   customs / declared-items editors — always get the full page width. A right-hand
   sidebar was tried, but on anything short of a huge monitor it stole the width
   those tables need. Below 880px mobile.css already gives a single column. */
@media (min-width: 881px) {
  .grid.cols-2.detail-2col { grid-template-columns: minmax(0, 1fr); }
}
/* Sidebar variant — pairs with the modal-editor pattern: a wide operational column
   + a width-capped History sidebar. The heavy editor lives in a modal, so the page
   column needn't be full-width. Single column on mobile (mobile.css). */
@media (min-width: 881px) {
  .grid.cols-2.detail-sidebar { grid-template-columns: minmax(0, 1fr) minmax(240px, 320px); }
}

/* ---- Modal (reusable) --------------------------------------------------- */
.modal-overlay { position: fixed; inset: 0; z-index: 100; background: rgba(17, 24, 39, .5);
  display: flex; align-items: flex-start; justify-content: center; padding: 28px 16px; overflow-y: auto; }
.modal-overlay[hidden] { display: none; }
.modal-dialog { background: var(--surface); border-radius: var(--radius); box-shadow: 0 24px 64px rgba(0,0,0,.32);
  width: 100%; max-width: 1000px; margin: auto; }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 20px; border-bottom: 1px solid var(--border); position: sticky; top: 0;
  background: var(--surface); border-radius: var(--radius) var(--radius) 0 0; z-index: 1; }
.modal-head .modal-title { font-size: 16px; font-weight: 700; }
.modal-x { background: none; border: 0; font-size: 26px; line-height: 1; cursor: pointer; color: var(--muted); padding: 0 4px; }
.modal-x:hover { color: var(--text-color); }
.modal-body { padding: 20px; }
@media (max-width: 880px) {
  .modal-overlay { padding: 0; }
  .modal-dialog { max-width: none; min-height: 100%; border-radius: 0; }
}

/* ---- Slide-over drawer (reuses .modal-overlay / .modal-dialog) ---------- */
.modal-overlay.drawer-right { justify-content: flex-end; align-items: stretch; padding: 0; overflow: hidden; }
.modal-overlay.drawer-right .modal-dialog { width: 100%; max-width: 640px; margin: 0; min-height: 100%;
  max-height: 100%; border-radius: 0; display: flex; flex-direction: column;
  box-shadow: -24px 0 64px rgba(0, 0, 0, .28); animation: drawer-in .18s ease-out; }
.modal-overlay.drawer-right .modal-body { flex: 1 1 auto; overflow-y: auto; padding: 16px; }
@keyframes drawer-in { from { transform: translateX(28px); opacity: .5; } to { transform: none; opacity: 1; } }
@media (max-width: 880px) { .modal-overlay.drawer-right .modal-dialog { max-width: none; } }

/* ---- Customer typeahead (assign drawer) -------------------------------- */
.ac-wrap { position: relative; }
.ac-menu { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 120;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .16); max-height: 320px; overflow-y: auto; }
.ac-menu[hidden] { display: none; }
.ac-item { display: block; padding: 8px 12px; text-decoration: none; color: inherit; cursor: pointer;
  border-bottom: 1px solid var(--border); }
.ac-item:last-child { border-bottom: 0; }
.ac-item:hover, .ac-item.active { background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
.ac-item .ac-name { display: block; font-weight: 600; font-size: 14px; }
.ac-item .ac-sub { display: block; font-size: 12px; color: var(--muted); margin-top: 1px; }

.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px; box-shadow: var(--shadow); }
.stat .label { color: var(--muted); font-size: 13px; }
.stat .value { font-size: 26px; font-weight: 700; margin-top: 4px; }
/* A stat or card rendered as a link keeps its look but gains a clear hover
   affordance (blue frame + subtle lift) so the whole tile reads as clickable. */
a.stat { display: block; }
a.stat, a.card { text-decoration: none; color: inherit;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
a.stat:hover, a.card:hover { border-color: var(--primary-color); box-shadow: 0 4px 14px rgba(0,0,0,.08); transform: translateY(-1px); }

/* ---- Switch (iOS-style on/off toggle) ----------------------------------- */
.switch { position: relative; display: inline-flex; align-items: center; vertical-align: middle; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 44px; height: 26px; border-radius: var(--radius-pill); background: #cbd5e1;
  transition: background .15s ease; cursor: pointer; flex: 0 0 auto;
}
.switch .track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 50%; background: #fff; box-shadow: var(--shadow); transition: transform .15s ease;
}
.switch input:checked + .track { background: var(--ok); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { outline: 2px solid var(--primary-color); outline-offset: 2px; }
.switch input:disabled + .track { opacity: .5; cursor: default; }

/* ---- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 22px; border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--surface); color: var(--text-color); font-weight: 600; cursor: pointer;
  font-size: 16px; min-height: 48px; text-decoration: none; transition: filter .12s ease, background .12s ease;
}
.btn:hover { text-decoration: none; filter: brightness(.98); }
.btn-primary { background: var(--button-color); border-color: var(--button-color); color: #fff; }
.btn-primary:hover { background: var(--button-hover-color, var(--button-color)); border-color: var(--button-hover-color, var(--button-color)); filter: var(--button-hover-filter, brightness(.93)); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-outline { background: transparent; border-color: var(--button-color); color: var(--button-color); }
.btn-outline:hover { background: var(--button-color); border-color: var(--button-color); color: #fff; filter: none; }
.btn-block { width: 100%; }
.btn-sm { padding: 7px 16px; min-height: 38px; font-size: 14px; }
.btn-lg { padding: 15px 28px; min-height: 56px; font-size: 17px; }
.btn:disabled, .btn[disabled] { opacity: .5; cursor: default; filter: none; }

/* ---- Forms -------------------------------------------------------------- */
.form-group { margin-bottom: 18px; }
.form-label { display: block; font-weight: 600; font-size: 15px; margin-bottom: 8px; color: var(--text-color); }
.form-control {
  width: 100%; padding: 14px 16px; border: 1px solid var(--field-border);
  border-radius: 14px; font-family: inherit; font-size: 16px; line-height: 1.4; min-height: 54px;
  background: var(--surface); color: var(--text-color);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.form-control::placeholder { color: var(--muted); }
.form-control:hover { border-color: color-mix(in srgb, var(--text-color) 35%, var(--field-border)); }
.form-control:focus { outline: none; border-color: var(--primary-color);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary-color) 18%, transparent); }
/* Read-only / disabled fields read as "not editable": light grey fill, muted text,
   and no interactive hover/focus affordance, so staff can tell them apart at a glance. */
.form-control[readonly], .form-control:disabled {
  background: var(--app-bg); color: var(--muted); border-color: var(--border);
}
.form-control:disabled { cursor: not-allowed; }
.form-control[readonly]:hover, .form-control:disabled:hover { border-color: var(--border); }
.form-control[readonly]:focus { border-color: var(--border); box-shadow: none; }
textarea.form-control { min-height: 96px; }
select.form-control { min-height: 54px; }
.form-hint { color: var(--muted); font-size: 13px; margin-top: 6px; }
.form-error { color: var(--danger); font-size: 13px; margin-top: 6px; }

/* ---- Tables ------------------------------------------------------------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.table { width: 100%; border-collapse: collapse; font-size: 15px; }
.table th, .table td { padding: 13px 16px; text-align: left; border-bottom: 1px solid var(--border); }
.table thead th { background: var(--table-header-color); font-weight: 700; font-size: 14px; white-space: nowrap; }
/* Dense customs/declared-items editor (partials/customs_lines_form): the default
   16px cell padding × 8 columns pushes the table past its card and forces a
   horizontal scrollbar. Tighten the cells (and their inputs) so every column fits. */
.decl-table th, .decl-table td { padding: 7px 6px; }
/* Top-align cells so every input lines up at the row top — otherwise the taller HS cell
   (input + its "870829 — …" description) centre-aligns the shorter cells and knocks the
   whole row out of line. The description then hangs neatly below the HS field. */
.decl-table td { vertical-align: top; }
.decl-table th:first-child, .decl-table td:first-child { padding-left: 2px; }
.decl-table th:last-child, .decl-table td:last-child { padding-right: 2px; }
.decl-table .form-control { padding-left: 8px; padding-right: 6px; }
/* Keep overflow VISIBLE on desktop so the category/HS keyword dropdown isn't clipped
   (overflow-x:auto would force overflow-y to clip too). The table already fits its
   card at these widths; only enable horizontal scroll once the viewport is too narrow
   to show every column. */
.decl-table-wrap { overflow: visible; }
@media (max-width: 1100px) {
  .decl-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}
/* Line-item inputs: hide the rarely-used number spinner on every repeatable
   item form ([data-rows]: purchase/forwarding create + edit) and the staff
   quote table, so multi-digit quantities/prices aren't crowded. The quote
   table's columns are especially narrow, so ALSO trim its field padding —
   otherwise the default 16px padding + spinner clipped values (e.g. Qty 20
   rendering as "2"). */
[data-quote-items] .form-control { padding-left: 10px; padding-right: 10px; }
[data-quote-items] input[type="number"],
[data-rows] input[type="number"] { -moz-appearance: textfield; }
[data-quote-items] input[type="number"]::-webkit-outer-spin-button,
[data-quote-items] input[type="number"]::-webkit-inner-spin-button,
[data-rows] input[type="number"]::-webkit-outer-spin-button,
[data-rows] input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.table tbody tr:last-child td { border-bottom: 0; }
/* Key-value info cards (label/value rows, no header) read as a divided list, so keep
   the divider on the LAST row too — the default last-row-borderless look (right for
   data grids) leaves it looking unfinished, and only the td border was dropped, which
   left an asymmetric half-line under the label. */
.info-table tbody tr:last-child th, .info-table tbody tr:last-child td { border-bottom: 1px solid var(--border); }
.info-table tbody tr:hover { background: transparent; }
.table tbody tr:hover { background: var(--surface-2); }
/* A cancelled/void row reads as struck-out: greyed text, background and thumbnail.
   Shared by the purchase and shipment lists (customer + staff) and the dashboard. */
.table tr.is-cancelled td { background: var(--surface-2); color: var(--muted); }
.table tr.is-cancelled td a { color: var(--muted); }
.table tr.is-cancelled td img { filter: grayscale(1); opacity: .5; }

/* ---- Badges ------------------------------------------------------------- */
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600; background: var(--surface-2); color: var(--text-color); border: 1px solid var(--border); }
.badge-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }

/* ---- Alerts ------------------------------------------------------------- */
.alert { padding: 12px 14px; border-radius: var(--radius-sm); border: 1px solid var(--border); margin-bottom: 16px; font-size: 14px; }
.alert-success { background: #ecfdf5; border-color: #a7f3d0; color: #065f46; }
.alert-error { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.alert-info { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }

/* ---- Auth layout -------------------------------------------------------- */
.auth-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--surface); }
.auth-card { width: 100%; max-width: 440px; background: var(--surface); border: 1px solid transparent;
  border-radius: var(--radius); box-shadow: none; padding: 8px 4px 4px; }
.auth-card .auth-brand { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 22px; font-weight: 800; font-size: 18px; }
.auth-card h1 { font-size: 1.9rem; text-align: center; }
.auth-card .auth-sub { text-align: center; color: var(--muted); font-size: 15px; margin-bottom: 26px; }
.auth-card .auth-foot { text-align: center; margin-top: 18px; font-size: 14px; color: var(--muted); }

/* ---- Brand logo image -------------------------------------------------- */
.brand-logo { display: block; width: auto; object-fit: contain; }
.topbar .brand .brand-logo { height: 32px; max-width: 180px; }
.auth-card .auth-brand .brand-logo { height: 42px; width: auto; max-width: 85%; object-fit: contain; margin: 0 auto; }
.site-header .site-logo .brand-logo { height: 36px; max-width: 200px; }

/* ---- Phone field with country-code picker ------------------------------- */
.phone-row { display: flex; gap: 8px; }
.phone-row .phone-cc { flex: 0 0 44%; min-width: 0; }
.phone-row .phone-num { flex: 1 1 auto; min-width: 0; }
/* Footer sits on a dark background: cap the size and invert lightness so dark
   logo parts become light/visible, while hue-rotate keeps colours (e.g. a red
   dot stays red rather than turning cyan). */
.site-footer .site-logo .brand-logo.footer-logo {
  max-height: 30px; max-width: 170px; height: auto; width: auto;
  filter: invert(1) hue-rotate(180deg);
}

/* ---- One-time-code (OTP) input ----------------------------------------- */
.otp { display: flex; gap: 10px; justify-content: center; }
.otp-box {
  width: 48px; height: 56px; text-align: center; font-size: 24px; font-weight: 700;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--text-color);
  -moz-appearance: textfield;
}
.otp-box:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(31, 111, 235, .15); }
.otp-box::-webkit-outer-spin-button, .otp-box::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
@media (max-width: 420px) {
  .otp { gap: 6px; }
  .otp-box { width: 42px; height: 50px; font-size: 20px; }
}

/* ---- Language switch / dropdown ---------------------------------------- */
.lang-switch { display: flex; gap: 4px; }
.lang-switch a { padding: 6px 10px; border-radius: var(--radius-sm); font-size: 13px; color: var(--muted); border: 1px solid transparent; }
.lang-switch a.active { color: var(--primary-color); border-color: var(--border); background: var(--surface-2); }

/* Compact globe language picker */
.lang-dd { position: relative; }
.lang-dd > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  height: 38px; padding: 0 10px; border-radius: var(--radius-sm); color: var(--muted); border: 1px solid var(--border); }
.lang-dd > summary::-webkit-details-marker { display: none; }
.lang-dd > summary svg { width: 20px; height: 20px; }
.lang-dd > summary .lang-cur { font-size: 14px; margin-left: 6px; font-weight: 600; white-space: nowrap; }
.lang-dd > summary .lang-caret { font-size: 10px; margin-left: 3px; opacity: .6; }
.lang-dd > summary:hover { background: var(--surface-2); color: var(--text-color); }
.lang-dd[open] > summary { background: var(--surface-2); color: var(--primary-color); }
.lang-dd-menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 60; min-width: 160px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow, 0 10px 30px rgba(2,6,23,.14)); display: flex; flex-direction: column; gap: 2px; }
.lang-dd-menu a { padding: 9px 12px; border-radius: var(--radius-sm); font-size: 14px; color: var(--text-color);
  text-decoration: none; white-space: nowrap; }
.lang-dd-menu a:hover { background: var(--surface-2); }
.lang-dd-menu a.active { color: var(--primary-color); font-weight: 600; background: var(--surface-2); }
/* App footer language row (matches the public site's Apple-style selector). */
.app-foot { border-top: 1px solid var(--border); background: var(--surface, #fff); padding: 16px 20px; }
.app-foot-lang { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; max-width: 1200px; margin: 0 auto; }
.app-foot-lang-label { color: var(--muted); font-size: 13px; display: inline-flex; align-items: center; gap: 6px; }
.app-foot-lang-label svg { width: 16px; height: 16px; }
.app-foot-lang a { color: var(--text-color); text-decoration: none; font-size: 14px; }
.app-foot-lang a:hover { color: var(--primary-color); }
.app-foot-lang a.active { color: var(--primary-color); font-weight: 700; }
@media (max-width: 880px) { .app-foot { margin-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); } }

.user-chip { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 600; }
.user-chip .avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--primary-color); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 12px; }

/* The mobile bottom-nav is defined in mobile.css and hidden on desktop. */
.mobile-nav { display: none; }

/* Language switch lives in the topbar on desktop; on mobile it moves into the
   slide-in sidebar drawer (this block is shown only there, via mobile.css). */
.sidebar-mobile-only { display: none; }
.sidebar-langs { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 12px 8px; }
.sidebar-langs a { padding: 7px 12px; border-radius: var(--radius-sm); font-size: 14px;
  color: var(--text-color); border: 1px solid var(--border); }
.sidebar-langs a.active { color: var(--primary-color); border-color: var(--primary-color); background: var(--surface-2); }
/* Member ID row inside the drawer (mobile) — full width, tap-to-copy, always fully
   readable (unlike the truncated topbar chip it replaces on mobile). */
.drawer-member-id { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: calc(100% - 24px); margin: 0 12px 8px; padding: 10px 12px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--primary-color) 35%, transparent);
  background: color-mix(in srgb, var(--primary-color) 8%, transparent);
  color: var(--text-color); border-radius: var(--radius-sm); }
.drawer-member-id strong { font-size: 16px; font-variant-numeric: tabular-nums; letter-spacing: .05em; }
.drawer-member-id svg { width: 17px; height: 17px; flex: 0 0 17px; color: var(--muted); }
.drawer-member-id.copied { border-color: var(--ok, #16a34a); background: color-mix(in srgb, var(--ok, #16a34a) 16%, transparent); }
.drawer-member-id.copied svg { color: var(--ok, #16a34a); }

/* ---- Membership tier card (premium status feel, not RPG) ---------------- */
/* Colours come from inline --tier / --tier-next set per rank on the card. */
.tier-card { margin-bottom: 16px; border-top: 3px solid var(--tier, var(--border)); }
.tier-head { display: flex; align-items: center; gap: 14px; }
/* Badge: a bare tier-coloured emblem (no chip), matching the rest of the page's
   icon treatment — the star / medal / crown carries the status on its own. */
.tier-badge { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; color: var(--tier, #6b7280); }
.tier-badge svg { width: 40px; height: 40px; }
.tier-label { font-size: .72em; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.tier-name { font-size: 1.5em; font-weight: 800; line-height: 1.15; color: var(--tier, var(--text-color)); }
.tier-usage { color: var(--muted); font-size: .85em; margin-top: 2px; }
.tier-progress-wrap { margin-top: 16px; max-width: 440px; }
.tier-progress-label { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: .85em; margin-bottom: 6px; }
.tier-progress-label .to-next { font-weight: 600; }
.tier-progress-label .count { color: var(--muted); font-variant-numeric: tabular-nums; }
.tier-track { height: 8px; border-radius: 99px; background: var(--surface-2, #f1f5f9); overflow: hidden;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 70%, transparent); }
/* min-width leaves a small rounded nub even at 0% so a brand-new member (0 / N)
   sees the start of the bar rather than an empty track that looks broken. */
.tier-fill { height: 100%; min-width: 10px; border-radius: 99px; transform-origin: left center;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--tier-next, var(--primary-color)) 78%, white),
    var(--tier-next, var(--primary-color)));
  animation: tier-grow .6s cubic-bezier(.22, .61, .36, 1) both; }
@keyframes tier-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .tier-fill { animation: none; } }
/* "Unlock at the next tier" preview — the payoff for the progress bar. */
.tier-unlock { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.tier-unlock-label { display: inline-flex; align-items: center; gap: 5px; font-size: .78em; font-weight: 600; color: var(--muted); }
.tier-unlock-label svg { width: 13px; height: 13px; }
.tier-chip { display: inline-flex; align-items: center; gap: 6px; font-size: .82em; font-weight: 600;
  padding: 4px 10px; border-radius: var(--radius-pill);
  color: color-mix(in srgb, var(--tier-next, var(--primary-color)) 72%, var(--text-color));
  background: color-mix(in srgb, var(--tier-next, var(--primary-color)) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--tier-next, var(--primary-color)) 26%, transparent); }
.tier-chip svg { width: 14px; height: 14px; }
.tier-top { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; font-size: .9em; font-weight: 600; color: var(--tier, var(--text-color)); }
.tier-top svg { width: 18px; height: 18px; }
.tier-divider { height: 1px; background: var(--border); margin: 16px 0 14px; }
.tier-perks-title { font-size: .72em; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; margin-bottom: 10px; }
.tier-perks { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.tier-perk { display: flex; align-items: center; gap: 10px; font-size: .92em; line-height: 1.25; }
/* Bare icon (no tinted chip), matching the quick-action tiles — fixed-width column
   so labels line up across rows. */
.tier-perk .ic { flex: 0 0 22px; display: flex; align-items: center; justify-content: center;
  color: var(--tier, var(--primary-color)); }
.tier-perk .ic svg { width: 20px; height: 20px; }

/* ---- "Add" tile (dashed, sits at the end of a card grid) ---------------- */
.address-add-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  min-height: 120px; text-align: center; text-decoration: none; font-weight: 600;
  color: var(--primary-color); box-shadow: none;
  border: 1.5px dashed color-mix(in srgb, var(--primary-color) 45%, var(--border));
  background: color-mix(in srgb, var(--primary-color) 4%, transparent); }
.address-add-tile:hover { text-decoration: none; border-color: var(--primary-color);
  background: color-mix(in srgb, var(--primary-color) 9%, transparent); }
.address-add-tile:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }
.address-add-tile .aat-plus { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px;
  border-radius: 50%; background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
.address-add-tile .aat-plus svg { width: 22px; height: 22px; }

/* ---- Quick actions (icon tiles) ----------------------------------------- */
/* Equal cells keep edges tidy at any label length / language (the label sits
   UNDER the icon, so narrow 2-up cells don't wrap awkwardly). The primary action
   is a full-width hero CTA on mobile and a uniform blue tile on wider screens. */
.quick-actions { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.qa-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  min-height: 96px; padding: 16px 10px; text-align: center; text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
  color: var(--text-color); font-weight: 600; font-size: 14px; line-height: 1.25;
  transition: background .12s ease, border-color .12s ease, transform .1s ease; }
.qa-tile:hover { background: var(--surface-2); border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border)); text-decoration: none; }
.qa-tile:active { transform: translateY(1px); }
.qa-tile:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }
/* Bare icon (no tinted chip) — simpler; sized up a touch and kept brand-blue so it
   still reads as a deliberate icon rather than a stray glyph. */
.qa-ic { display: flex; align-items: center; justify-content: center; color: var(--primary-color); }
.qa-ic svg { width: 26px; height: 26px; }
.qa-tile.qa-primary { grid-column: 1 / -1; flex-direction: row; gap: 10px; min-height: auto; padding: 15px 18px;
  background: var(--button-color); border-color: var(--button-color); color: #fff; font-size: 15px; }
.qa-tile.qa-primary .qa-ic { color: #fff; }
.qa-tile.qa-primary:hover { background: var(--button-hover-color, var(--button-color)); filter: var(--button-hover-filter, brightness(.95)); }
@media (min-width: 620px) {
  .quick-actions { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .qa-tile.qa-primary { grid-column: auto; flex-direction: column; min-height: 96px; padding: 16px 10px; font-size: 14px; }
}

/* ---- Utilities ---------------------------------------------------------- */
.text-muted { color: var(--muted); }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.flex { display: flex; } .items-center { align-items: center; } .items-end { align-items: flex-end; } .justify-between { justify-content: space-between; }
.gap-2 { gap: 8px; } .gap-3 { gap: 12px; } .wrap { flex-wrap: wrap; }

/* Responsive show/hide (mobile-first base) */
.hide-mobile { display: none; }
@media (min-width: 881px) {
  .hide-mobile { display: inline; }
  .hide-desktop { display: none; }
}


/* --- Public nav dropdown ---------------------------------------------------
   Single-line items. The row itself is the affordance (hover surface + chevron);
   the text is NOT styled as a blue underlined link, which reads dated in a menu.
   Built on <details> so it works without JS.
   NOTE: the trigger's typography lives in public.css next to `.site-nav > a`, so a
   dropdown label and a plain nav label are guaranteed to match. */
.nav-dd { position: relative; }
.nav-dd > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
                    user-select: none; }
.nav-dd > summary::-webkit-details-marker { display: none; }

/* Chevron drawn in CSS so it inherits the text colour and animates cleanly. */
.nav-dd-caret { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
                transform: rotate(45deg) translate(-1px, -1px); opacity: .45;
                transition: transform .18s ease, opacity .18s ease; }
.nav-dd[open] .nav-dd-caret { transform: rotate(225deg) translate(-2px, -2px); opacity: .9; }

.nav-dd-menu { position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%);
               z-index: 60; min-width: 200px; padding: 6px;
               background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
               box-shadow: 0 1px 2px rgba(16,24,40,.04), 0 12px 32px -8px rgba(16,24,40,.16);
               display: flex; flex-direction: column; gap: 2px;
               animation: navDdIn .16s ease; }
@keyframes navDdIn { from { opacity: 0; transform: translateX(-50%) translateY(-4px); } }

.nav-dd-menu a { display: block; padding: 9px 12px; border-radius: 9px; white-space: nowrap;
                 text-decoration: none; color: var(--text-color);
                 font-size: 14px; font-weight: 500; line-height: 1.4;
                 transition: background .12s ease; }
.nav-dd-menu a:hover,
.nav-dd-menu a:focus-visible { background: var(--surface-2); text-decoration: none; }

/* Mobile: the nav is a stacked drawer, so the menu flows inline instead of floating —
   a centred absolute panel would hang off the edge of the screen. */
@media (max-width: 900px) {
  .nav-dd { width: 100%; }
  .nav-dd > summary { justify-content: space-between; width: 100%; }
  .nav-dd-menu { position: static; transform: none; min-width: 0; width: 100%;
                 border: 0; box-shadow: none; background: transparent;
                 padding: 2px 0 6px 12px; animation: none; }
  .nav-dd-menu a { padding: 9px 6px; white-space: normal; }
}

/* ---- Drawer wallet (mobile) --------------------------------------------
   The balance moved out of the mobile top bar, where it was wide enough to
   push the language switcher off the right edge. Given more room here it can
   show the label and full JPY amount that the chip had to abbreviate. */
.drawer-wallet { margin: 12px 12px 4px; border-radius: var(--radius-sm);
  border: 1px solid color-mix(in srgb, var(--primary-color) 35%, transparent);
  background: color-mix(in srgb, var(--primary-color) 8%, transparent); overflow: hidden; }
.drawer-wallet-amt { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  text-decoration: none; color: var(--text-color); }
.drawer-wallet-amt svg { width: 20px; height: 20px; flex: 0 0 20px; color: var(--primary-color); }
.drawer-wallet-amt small { display: block; font-size: 11px; color: var(--muted); line-height: 1.3; }
.drawer-wallet-amt strong { display: block; font-size: 17px; font-variant-numeric: tabular-nums; }
.drawer-wallet-add { display: block; padding: 8px 12px; text-align: center; font-size: 13px; font-weight: 600;
  text-decoration: none; color: var(--primary-color);
  border-top: 1px solid color-mix(in srgb, var(--primary-color) 25%, transparent); }
.drawer-wallet-add:hover { background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
/* A negative balance is the one case worth shouting about — it blocks new orders. */
.drawer-wallet.is-neg { border-color: color-mix(in srgb, var(--danger, #dc2626) 45%, transparent);
  background: color-mix(in srgb, var(--danger, #dc2626) 8%, transparent); }
.drawer-wallet.is-neg .drawer-wallet-amt strong { color: var(--danger, #dc2626); }
.drawer-wallet.is-neg .drawer-wallet-amt svg { color: var(--danger, #dc2626); }
