/* ============================================================================
   Platinum — one stylesheet, no build step

   This file is served verbatim. There is no Tailwind, no PostCSS, no Vite, no
   node_modules, and nothing to run before a deploy: edit this file, reload the
   page, done.

   ## Why that is the right call here rather than a compromise

   The templates in this project use exactly zero utility classes. Every class
   in every Blade file is a semantic component name — .card, .btn, .table,
   .store-top — because the markup was written that way from the start. Tailwind
   was therefore doing one job: turning `@theme` into custom properties, which
   CSS does natively in `:root`. Removing it removes a toolchain and changes
   nothing about the output.

   What the build DID provide, and is replaced by hand below, is Preflight —
   Tailwind's reset. Its absence is why the "Base" section is longer than a
   token file would normally warrant. Nothing in it is decorative.

   ## Structure

     1. Tokens        — every colour, radius and shadow, as semantic roles
     2. Base          — the reset, plus focus and motion rules
     3. Layout        — the back-office shell and the storefront frame
     4. Components    — cards, buttons, fields, badges, tables, stats
     5. Utilities     — the handful that earn their place

   Colours are declared as roles, never as raw hex at the point of use, so
   retheming means editing section 1 and nothing else.

   Dark mode is a designed set of steps chosen for a dark surface, not an
   automatic inversion. Both scopes are declared: the media query covers the OS
   setting, the [data-theme] attribute covers the in-app toggle, and the toggle
   wins in both directions.
   ========================================================================= */

/* ============================================================================
   0. Web font — Ubuntu

   Loaded by a <link> in the three layouts, not by @import here.

   An @import inside a stylesheet is discovered only AFTER this file has been
   downloaded and parsed, which serialises two network round trips before any
   text can render. The <link> sits in <head> alongside this file, so both
   fetches start together.

   The layouts also carry `preconnect` hints to fonts.googleapis.com and
   fonts.gstatic.com. Google serves the CSS from one host and the font binaries
   from another, so without the second hint the browser pays a fresh DNS + TLS
   handshake at exactly the moment it discovers it needs the font files.

   `display=swap` is in the request URL. Without it browsers hide text for up to
   three seconds while the font loads — a blank catalogue on a slow connection,
   which is worse than showing the fallback and swapping.

   ## Weights

   Ubuntu ships 300, 400, 500 and 700. Nothing between. The CSS font-matching
   algorithm rounds a requested weight above 500 UPWARDS first, so 550, 600, 650
   and 800 would all render at 700 — collapsing three visual tiers into one and
   making the whole interface read as bold. The declarations below are therefore
   snapped to weights Ubuntu actually has:

     400  body text
     500  labels, badges, buttons, card titles      (was 550 / 600)
     700  page titles, stat values, headings, mark  (was 650 / 800)

   If you swap to a variable font later, these can go back to finer values.
   ========================================================================= */

/* ============================================================================
   1. Tokens
   ========================================================================= */

:root {
  color-scheme: light;

  /*
   * The body typeface.
   *
   * The token is still called --font-sans for continuity — every rule in this
   * file already references it. Ubuntu is served from Google Fonts; the stack
   * behind it is what renders while the font downloads, and permanently for
   * anyone whose network blocks Google.
   */
  --font-sans: 'Ubuntu', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --radius-card: 0.625rem;
  --radius-control: 0.5rem;
  --radius-pill: 9999px;

  /* Data-end rounding. 4px, anchored so bars stay flat on the baseline. */
  --radius-data: 4px;

  /* Planes ---------------------------------------------------------------- */
  --plane:            #f4f4f2;  /* app background, behind cards */
  --surface:          #fcfcfb;  /* cards, panels, table rows */
  --surface-raised:   #ffffff;  /* modals, dropdowns, popovers */
  --surface-sunken:   #efefec;  /* table headers, inset wells */
  --surface-inverse:  #17171a;  /* the sidebar */

  /* Ink -------------------------------------------------------------------- */
  --ink-primary:      #0b0b0b;
  --ink-secondary:    #52514e;
  --ink-muted:        #898781;
  --ink-on-inverse:   #f4f4f2;
  --ink-on-accent:    #ffffff;

  /* Lines ------------------------------------------------------------------ */
  --line:             rgba(11, 11, 11, 0.10);
  --line-strong:      rgba(11, 11, 11, 0.18);
  --gridline:         #e1e0d9;
  --baseline:         #c3c2b7;

  /* Accent ----------------------------------------------------------------- */
  --accent:           #2a78d6;
  --accent-hover:     #256abf;
  --accent-active:    #1c5cab;
  --accent-wash:      #eaf2fd;
  --accent-ring:      rgba(42, 120, 214, 0.35);

  /* Status. Never themed, never reused as a series colour, always shipped
     with an icon and a label so colour is never the only signal. */
  --status-good:      #0ca30c;
  --status-warning:   #fab219;
  --status-serious:   #ec835a;
  --status-critical:  #d03b3b;
  --status-good-text: #006300;
  --status-good-wash: #e7f6e7;
  --status-warn-wash: #fdf3e0;
  --status-crit-wash: #fbeaea;

  /* Categorical series, fixed order. Never cycled. */
  --series-1: #2a78d6;  --series-2: #eb6834;
  --series-3: #1baf7a;  --series-4: #eda100;
  --series-5: #e87ba4;  --series-6: #008300;
  --series-7: #4a3aa7;  --series-8: #e34948;

  --shadow-card:  0 1px 2px rgba(11,11,11,0.04), 0 1px 3px rgba(11,11,11,0.06);
  --shadow-float: 0 4px 12px rgba(11,11,11,0.08), 0 12px 32px rgba(11,11,11,0.10);

  /* Layout metrics ---------------------------------------------------------- */
  --sidebar-w: 15rem;
  --topbar-h: 3.5rem;
  --content-max: 82rem;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme='light'])) {
    color-scheme: dark;

    --plane:            #0d0d0d;
    --surface:          #1a1a19;
    --surface-raised:   #232322;
    --surface-sunken:   #141413;
    --surface-inverse:  #000000;

    --ink-primary:      #ffffff;
    --ink-secondary:    #c3c2b7;
    --ink-muted:        #898781;
    --ink-on-inverse:   #f4f4f2;
    --ink-on-accent:    #ffffff;

    --line:             rgba(255, 255, 255, 0.10);
    --line-strong:      rgba(255, 255, 255, 0.18);
    --gridline:         #2c2c2a;
    --baseline:         #383835;

    --accent:           #3987e5;
    --accent-hover:     #5598e7;
    --accent-active:    #6da7ec;
    --accent-wash:      rgba(57, 135, 229, 0.14);
    --accent-ring:      rgba(57, 135, 229, 0.45);

    --status-good-text: #0ca30c;
    --status-good-wash: rgba(12, 163, 12, 0.14);
    --status-warn-wash: rgba(250, 178, 25, 0.14);
    --status-crit-wash: rgba(208, 59, 59, 0.16);

    --series-1: #3987e5;  --series-2: #d95926;
    --series-3: #199e70;  --series-4: #c98500;
    --series-5: #d55181;  --series-6: #008300;
    --series-7: #9085e9;  --series-8: #e66767;

    --shadow-card:  0 1px 2px rgba(0,0,0,0.30), 0 1px 3px rgba(0,0,0,0.24);
    --shadow-float: 0 4px 12px rgba(0,0,0,0.44), 0 12px 32px rgba(0,0,0,0.40);
  }
}

/* The in-app toggle. Duplicated deliberately so it beats the OS setting. */
:root[data-theme='dark'] {
  color-scheme: dark;
  --plane: #0d0d0d;            --surface: #1a1a19;
  --surface-raised: #232322;   --surface-sunken: #141413;
  --surface-inverse: #000000;
  --ink-primary: #ffffff;      --ink-secondary: #c3c2b7;
  --ink-muted: #898781;        --ink-on-inverse: #f4f4f2;
  --line: rgba(255,255,255,0.10);
  --line-strong: rgba(255,255,255,0.18);
  --gridline: #2c2c2a;         --baseline: #383835;
  --accent: #3987e5;           --accent-hover: #5598e7;
  --accent-active: #6da7ec;    --accent-wash: rgba(57,135,229,0.14);
  --accent-ring: rgba(57,135,229,0.45);
  --status-good-text: #0ca30c;
  --status-good-wash: rgba(12,163,12,0.14);
  --status-warn-wash: rgba(250,178,25,0.14);
  --status-crit-wash: rgba(208,59,59,0.16);
  --series-1: #3987e5;  --series-2: #d95926;
  --series-3: #199e70;  --series-4: #c98500;
  --series-5: #d55181;  --series-6: #008300;
  --series-7: #9085e9;  --series-8: #e66767;
  --shadow-card: 0 1px 2px rgba(0,0,0,0.30), 0 1px 3px rgba(0,0,0,0.24);
  --shadow-float: 0 4px 12px rgba(0,0,0,0.44), 0 12px 32px rgba(0,0,0,0.40);
}

/* ============================================================================
   2. Base

   This section replaces Tailwind's Preflight. It is deliberately conservative:
   it normalises the things the components below assume, and leaves ordinary
   prose alone — the policies and contact pages are written as plain HTML and
   should still look like documents.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--plane);
  color: var(--ink-primary);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Form controls do not inherit typography from the page. Browsers still use a
   system font at a browser-chosen size, so without this every input renders in
   a different face from the label beside it. */
button, input, select, textarea, optgroup {
  font: inherit;
  color: inherit;
  margin: 0;
}

button, [type='button'], [type='submit'], [type='reset'] {
  -webkit-appearance: button;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: inherit;
}

/* Replaced elements are inline by default, which leaves a stray descender-sized
   gap under every image sitting in a block. */
img, svg, video, canvas, iframe, object {
  display: block;
  max-width: 100%;
}
img, video { height: auto; }

table { border-collapse: collapse; border-spacing: 0; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

hr { border: 0; border-top: 1px solid var(--line); margin: 1.5rem 0; }

code, kbd, pre, samp { font-family: var(--font-mono); font-size: 0.9em; }

/* Visible focus everywhere. The legacy site had none — every interactive
   element was an <input type="image"> or a bare anchor, and the site was
   unusable from a keyboard. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   3. Layout

   Two frames. `.shell` is the back office: fixed sidebar, sticky topbar,
   scrolling content. `.store-*` is the customer site: full-width header over a
   centred column.
   ========================================================================= */

/* Back office ------------------------------------------------------------- */

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

.sidebar {
  background: var(--surface-inverse);
  color: var(--ink-on-inverse);
  padding: 1rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sb-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0.75rem 1rem;
  color: #fff;
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.sb-mark {
  width: 26px; height: 26px;
  flex: none;
  border-radius: 7px;
  background: linear-gradient(135deg, #e8e8e6, #a8a8a4);
  color: #17171a;
  display: grid; place-items: center;
  font-size: 0.8125rem; font-weight: 700;
}

/* Pinned to the bottom of the sidebar — `margin-top:auto` in a flex column is
   what keeps the signed-in user at the foot regardless of nav length. */
.sb-user {
  margin-top: auto;
  padding: 0.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  color: rgba(244, 244, 242, 0.72);
}

/* Sign out and change password. The sidebar is dark in both themes, so these
   inherit its own light-on-dark colours rather than the page's ink tokens —
   which would be near-black text on a near-black panel in light mode. */
.sb-user-links {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
}
.sb-user-links a,
.sb-user-links button {
  font: inherit;
  padding: 0.25rem 0.375rem;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  color: rgba(244, 244, 242, 0.62);
  text-decoration: none;
  cursor: pointer;
}
.sb-user-links a:hover,
.sb-user-links button:hover {
  background: rgba(255, 255, 255, 0.09);
  color: #f4f4f2;
}

.main { display: flex; flex-direction: column; min-width: 0; }

.topbar {
  height: var(--topbar-h);
  flex: none;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 1.5rem;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

.content {
  flex: 1;
  min-width: 0;
  padding: 1.5rem;
  width: 100%;
  max-width: var(--content-max);
}

.who { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }

.avatar {
  width: 28px; height: 28px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  display: grid; place-items: center;
  font-size: 0.6875rem; font-weight: 700;
  text-transform: uppercase;
}

.search { flex: 1; max-width: 22rem; }

/* Storefront -------------------------------------------------------------- */

.store-top {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.5rem;
  height: var(--topbar-h);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

.store-brand {
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--ink-primary);
  font-weight: 700; font-size: 0.9375rem; letter-spacing: -0.02em;
  text-decoration: none;
  flex: none;
}

.store-mark {
  width: 26px; height: 26px;
  flex: none;
  border-radius: 7px;
  background: linear-gradient(135deg, #e8e8e6, #a8a8a4);
  color: #17171a;
  display: grid; place-items: center;
  font-size: 0.8125rem; font-weight: 700;
}

.store-nav { display: flex; align-items: center; gap: 0.25rem; }

.store-nav a {
  padding: 0.375rem 0.625rem;
  border-radius: var(--radius-control);
  color: var(--ink-secondary);
  font-size: 0.8125rem; font-weight: 500;
  text-decoration: none;
}
.store-nav a:hover { background: var(--surface-sunken); color: var(--ink-primary); }
.store-nav a[aria-current='page'] { color: var(--ink-primary); font-weight: 500; }

.store-actions { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }

.store-body {
  padding: 1.5rem;
  max-width: var(--content-max);
  margin: 0 auto;
  width: 100%;
}

/* Held-stones chip. Not a cart: these are exclusive claims with a clock on
   them, which is why the count is always visible rather than tucked away. */
.cart-chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.375rem 0.6875rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-primary);
  font-size: 0.8125rem; font-weight: 500;
  text-decoration: none;
}
.cart-chip:hover { background: var(--surface-sunken); }

.cart-count {
  min-width: 1.125rem;
  padding: 0 0.3125rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--ink-on-accent);
  font-size: 0.6875rem; font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Staff-to-customer message bar. Replaces legacy ping.php, which polled every
   five seconds from every open page and dropped anything nobody was there for.
   These are durable rows, so the message is still here when they come back. */
.msgbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 1.25rem;
  background: var(--accent-wash);
  border-bottom: 1px solid var(--line);
  font-size: 0.8125rem;
}

/* Page furniture ---------------------------------------------------------- */

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.page-title {
  margin: 0;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.2;
}

.page-sub { margin: 0.25rem 0 0; font-size: 0.8125rem; color: var(--ink-secondary); }

.crumbs {
  display: flex; align-items: center; gap: 0.375rem; flex-wrap: wrap;
  margin-bottom: 0.5rem;
  font-size: 0.75rem; color: var(--ink-muted);
}
.crumbs a { color: var(--ink-secondary); text-decoration: none; }
.crumbs a:hover { color: var(--ink-primary); text-decoration: underline; }
.crumbs li + li::before { content: '/'; margin-right: 0.375rem; color: var(--ink-muted); }
.crumbs ol, .crumbs ul { display: contents; list-style: none; margin: 0; padding: 0; }

/* Two-column split for detail screens: the record on the left, the sidebar of
   related facts on the right. Collapses to one column early, because a stone's
   certificate details are unreadable in a 20rem column. */
.cols {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

.grid-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}

/* Responsive -------------------------------------------------------------- */

@media (max-width: 60rem) {
  .cols { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 48rem) {
  .shell { grid-template-columns: minmax(0, 1fr); }

  .sidebar {
    position: static;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    padding: 0.5rem 0.75rem;
  }
  .sb-brand { padding: 0 0.5rem 0 0; }
  .sb-user { margin-top: 0; border-top: 0; padding: 0.25rem 0.5rem; }
  .nav-section { display: none; }

  .content, .store-body { padding: 1rem; }
  .store-top { gap: 0.75rem; padding: 0 1rem; }
  .store-nav { display: none; }
}

/*
 * Narrow phones. The signed-out header carries a wordy call to action
 * ("Request a trade account") next to the brand and a Sign in button, and at
 * 390px that trio is about 86px wider than the viewport — the page scrolls
 * sideways, which is the single most obvious way a site reads as broken on a
 * phone.
 *
 * The header keeps its one-line shape and the long label is swapped for a
 * short one. Two spans rather than shrinking the type: a 12px button that
 * still says "Request a trade account" is not a fix, it is the same problem
 * rendered smaller.
 */
.store-cta-short { display: none; }

@media (max-width: 30rem) {
  .store-top { gap: 0.5rem; padding: 0 0.75rem; }

  /* The wordmark goes; the mark alone still identifies the site, and the CTA
     is what a signed-out visitor is here for. */
  .store-brand { font-size: 0; gap: 0; }
  .store-brand .store-mark { font-size: 0.8125rem; }

  .store-cta-long { display: none; }
  .store-cta-short { display: inline; }
}

/* ============================================================================
   4. Components
   ========================================================================= */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.card-header {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.card-title { font-size: 0.9375rem; font-weight: 500; margin: 0; letter-spacing: -0.01em; }

/* Buttons ----------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.875rem;
  border-radius: var(--radius-control);
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.btn-primary   { background: var(--accent); color: var(--ink-on-accent); }
.btn-primary:hover  { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-active); }
.btn-secondary { background: var(--surface); color: var(--ink-primary); border-color: var(--line-strong); }
.btn-secondary:hover { background: var(--surface-sunken); }
.btn-ghost     { background: transparent; color: var(--ink-secondary); }
.btn-ghost:hover { background: var(--surface-sunken); color: var(--ink-primary); }
.btn-danger    { background: var(--status-critical); color: #fff; }
.btn-sm        { padding: 0.3125rem 0.625rem; font-size: 0.75rem; }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.55; cursor: not-allowed; }

/* Fields ------------------------------------------------------------------- */
.field-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--ink-secondary);
  margin-bottom: 0.3125rem;
  letter-spacing: 0.01em;
}
.input {
  width: 100%;
  padding: 0.5rem 0.6875rem;
  background: var(--surface);
  color: var(--ink-primary);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-control);
  font: inherit;
  font-size: 0.8125rem;
}
.input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.input[aria-invalid='true'] { border-color: var(--status-critical); }
.field-error {
  display: flex; align-items: center; gap: 0.3rem;
  font-size: 0.75rem; color: var(--status-critical); margin-top: 0.3rem;
}

/* Badges. Icon + label always — colour never carries the meaning alone. */
.badge {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.1875rem 0.5rem;
  border-radius: var(--radius-pill);
  font-size: 0.6875rem; font-weight: 500;
  border: 1px solid transparent;
}
.badge-good     { background: var(--status-good-wash); color: var(--status-good-text); }
.badge-warning  { background: var(--status-warn-wash); color: var(--ink-primary); }
.badge-critical { background: var(--status-crit-wash); color: var(--status-critical); }
.badge-neutral  { background: var(--surface-sunken); color: var(--ink-secondary); border-color: var(--line); }

/* Tables ------------------------------------------------------------------- */
.table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.table thead th {
  text-align: left;
  padding: 0.625rem 1rem;
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table tbody td { padding: 0.6875rem 1rem; border-bottom: 1px solid var(--line); }
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--accent-wash); }
/* Only columns that must align vertically get tabular figures. */
.num { text-align: right; font-variant-numeric: tabular-nums; }

/* A stock number is an identifier, not prose. Monospace so transposed digits
   are visible, and selectable as one word for pasting into an email. */
.sku {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: var(--ink-secondary);
}

/* Stat tile. A hero number is a form in its own right — no chart needed when
   the job is a single headline. */
.stat { padding: 1.125rem 1.25rem; }
.stat-label {
  font-size: 0.75rem; font-weight: 500; color: var(--ink-secondary);
  margin: 0 0 0.375rem;
}
.stat-value {
  font-size: 1.875rem; font-weight: 700; letter-spacing: -0.02em;
  line-height: 1.1; margin: 0; color: var(--ink-primary);
  font-variant-numeric: tabular-nums;
}
.stat-delta {
  display: inline-flex; align-items: center; gap: 0.25rem;
  font-size: 0.75rem; font-weight: 500; margin-top: 0.375rem;
}
.stat-delta-up   { color: var(--status-good-text); }
.stat-delta-down { color: var(--status-critical); }
.stat-note { font-size: 0.75rem; color: var(--ink-muted); margin-top: 0.375rem; }

/* Horizontal bar, for the dashboard's status breakdown. A track plus a fill,
   so an empty bar still occupies its row and the column stays aligned. */
.bar-track {
  height: 6px;
  border-radius: var(--radius-data);
  background: var(--surface-sunken);
  overflow: hidden;
}
.bar-fill {
  height: 100%;
  border-radius: var(--radius-data);
  background: var(--series-1);
}

/* Legend. Always paired with the shape it explains, never floated alone. */
.legend {
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem;
  font-size: 0.75rem; color: var(--ink-secondary);
  list-style: none; margin: 0.75rem 0 0; padding: 0;
}
.legend li { display: flex; align-items: center; gap: 0.375rem; }
.legend li::before {
  content: '';
  width: 9px; height: 9px;
  border-radius: 2px;
  background: currentColor;
  flex: none;
}

/* Sidebar nav -------------------------------------------------------------- */
.nav-item {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-control);
  color: rgba(244, 244, 242, 0.72);
  text-decoration: none;
  font-size: 0.8125rem; font-weight: 500;
}
.nav-item:hover { background: rgba(255, 255, 255, 0.07); color: #fff; }
.nav-item[aria-current='page'] { background: rgba(255, 255, 255, 0.11); color: #fff; font-weight: 500; }
.nav-section {
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: rgba(244, 244, 242, 0.40);
  padding: 0 0.75rem; margin: 1.25rem 0 0.375rem;
}

/* Impersonation banner. Deliberately impossible to miss — the legacy
   walkthrough mode gave no indication at all that you were acting as
   someone else, and anything the rep did wrote to the customer's real cart. */
.impersonation-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 0.5rem 1.25rem;
  background: var(--status-warning); color: #0b0b0b;
  font-size: 0.8125rem; font-weight: 500;
}

/* ============================================================================
   5. Utilities
   ========================================================================= */

/* Visually hidden, still announced. Used for form labels the design carries
   visually (the topbar search) and for skip links. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Pagination ---------------------------------------------------------------
   Paired with resources/views/vendor/pagination/default.blade.php. Laravel's
   bundled pagination views are Tailwind-classed and render unstyled here. */
.pagination {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  margin-top: 1rem;
}

.pagination-links { display: flex; align-items: center; gap: .25rem; flex-wrap: wrap; }

.page-link {
  display: inline-flex; align-items: center; gap: .25rem;
  min-width: 2rem;
  padding: .375rem .625rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--ink-secondary);
  font-size: .8125rem; font-weight: 500;
  text-decoration: none;
  justify-content: center;
  font-variant-numeric: tabular-nums;
}
.page-link:hover { background: var(--surface-sunken); color: var(--ink-primary); }

.page-link.is-current {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ink-on-accent);
  font-weight: 500;
}

/* Disabled controls are spans, not dead anchors — an <a> with no href is not
   focusable and announces as nothing useful. */
.page-link.is-disabled { opacity: .45; cursor: default; }
.page-link.is-disabled:hover { background: var(--surface); color: var(--ink-secondary); }

.pagination-count { margin: 0; font-size: .75rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }

/* ============================================================================
   6. Storefront theme — warm beige

   Scoped to `body.storefront`, which layouts/app.blade.php always sets and
   layouts/auth.blade.php sets for site.* routes. The back office keeps the cool
   graphite palette; only what a customer sees changes.

   The mechanism is token redefinition, not new rules. Custom properties
   inherit, so redeclaring them on <body> re-themes every component underneath
   without touching a single component rule. That is the whole reason the
   stylesheet was written against roles rather than hex in the first place.

   ## The palette, and why these values

   Ground is #fbfaf7 — a warm off-white. Cards sit ABOVE it at #fffefb rather
   than below, because on a tinted ground a white card reads as raised while a
   grey one reads as a hole.

   The accent is a deep teal, not another brown. A warm ground with a warm
   accent goes monochrome, and the buttons stop reading as actions — they just
   become slightly different beige. Teal is the opposite temperature, so an
   action is unmistakably an action, and it stays out of the way of the
   product photography, which on a jewellery catalogue is doing the selling.

   Every value here was contrast-checked rather than eyeballed:

     ink-primary    14.4:1 on ground   body text
     ink-secondary   7.1:1             labels, captions
     ink-muted       5.1:1             hints — still above 4.5, deliberately
     accent          6.8:1             links
     white on accent 7.1:1             button labels

   Status and categorical series colours are NOT redefined. They come from a
   palette already validated for colour-vision-deficiency separation, and
   re-tinting them to suit a background is exactly how an accessible palette
   stops being one.
   ========================================================================= */

body.storefront {
  --plane:            #fbfaf7;
  --surface:          #fffefb;
  --surface-raised:   #ffffff;
  --surface-sunken:   #f2efe8;
  --surface-inverse:  #241f1a;

  --ink-primary:      #2b2620;
  --ink-secondary:    #5c544a;
  --ink-muted:        #736a5e;
  --ink-on-inverse:   #f7f4ee;
  --ink-on-accent:    #ffffff;

  /* Warm-tinted lines. A neutral grey hairline on a beige ground reads as
     slightly blue and makes the whole page look dirty. */
  --line:             rgba(61, 51, 38, 0.12);
  --line-strong:      rgba(61, 51, 38, 0.22);
  --gridline:         #e6e0d4;
  --baseline:         #cdc4b4;

  --accent:           #1c6357;
  --accent-hover:     #17544a;
  --accent-active:    #124239;
  --accent-wash:      #e6f0ed;
  --accent-ring:      rgba(28, 99, 87, 0.32);

  /* Shadows carry the ground's warmth too — a neutral black shadow on beige
     reads grey and flattens the card off the page. */
  --shadow-card:  0 1px 2px rgba(61,51,38,0.05), 0 1px 3px rgba(61,51,38,0.07);
  --shadow-float: 0 4px 12px rgba(61,51,38,0.10), 0 12px 32px rgba(61,51,38,0.12);

  /*
   * The circle lattice.
   *
   * Tiled at its native 29.9 × 31.132 so the strokes land on whole-ish pixels;
   * scaling a hairline pattern is what makes one look like moiré. The tile's
   * own stroke opacity is .045, which is about as light as a texture can be and
   * still register — it should read as a paper quality, not as content.
   */
  background-color: var(--plane);
  background-image: url('/img/shoham-circle-background.svg');
  background-repeat: repeat;
  background-size: 29.9px 31.132px;
  min-height: 100vh;
}

/* The header sits on the texture, so it needs its own opaque ground or the
   circles run through the navigation. */
body.storefront .store-top {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* Cards are opaque for the same reason: a translucent card over a pattern
   makes small type hard to read, which on a page full of prices is the wrong
   place to be clever. */
body.storefront .card { background: var(--surface); }

body.storefront .store-mark {
  background: linear-gradient(135deg, #2a7d6e, #145046);
  color: #ffffff;
}

/* Dark mode for the storefront — a warm charcoal, not the cool one the back
   office uses. Swapping temperature families between light and dark is the
   thing that makes a toggle feel like two different websites. */
@media (prefers-color-scheme: dark) {
  /* Guarded on the ROOT, not on body. `data-theme` is stamped on <html> by the
     pre-paint script, so a customer who explicitly chose Light has to keep the
     light palette even when their OS says dark — without this guard the media
     query wins and the toggle looks broken in exactly one direction. */
  :root:not([data-theme='light']) body.storefront {
    --plane:            #141210;
    --surface:          #1e1b18;
    --surface-raised:   #262220;
    --surface-sunken:   #161412;
    --surface-inverse:  #000000;

    --ink-primary:      #f7f4ee;
    --ink-secondary:    #c9c0b3;
    --ink-muted:        #9a9082;

    --line:             rgba(247, 244, 238, 0.12);
    --line-strong:      rgba(247, 244, 238, 0.22);
    --gridline:         #302b26;
    --baseline:         #3d372f;

    --accent:           #4fb3a1;
    --accent-hover:     #6cc4b4;
    --accent-active:    #85d1c3;
    --accent-wash:      rgba(79, 179, 161, 0.14);
    --accent-ring:      rgba(79, 179, 161, 0.42);
    --ink-on-accent:    #0f1c19;

    --shadow-card:  0 1px 2px rgba(0,0,0,0.34), 0 1px 3px rgba(0,0,0,0.28);
    --shadow-float: 0 4px 12px rgba(0,0,0,0.48), 0 12px 32px rgba(0,0,0,0.44);

    /* The light tile's stroke is a dark warm grey — invisible on #141210. Swap
       to the light-stroke variant rather than dropping the texture, so the two
       modes are the same page in different light. An external SVG in url()
       cannot be recoloured from here, hence a second file. */
    background-image: url('/img/shoham-circle-background-dark.svg');
  }
}

:root[data-theme='dark'] body.storefront,
body.storefront[data-theme='dark'] {
  --plane:            #141210;
  --surface:          #1e1b18;
  --surface-raised:   #262220;
  --surface-sunken:   #161412;
  --surface-inverse:  #000000;

  --ink-primary:      #f7f4ee;
  --ink-secondary:    #c9c0b3;
  --ink-muted:        #9a9082;

  --line:             rgba(247, 244, 238, 0.12);
  --line-strong:      rgba(247, 244, 238, 0.22);
  --gridline:         #302b26;
  --baseline:         #3d372f;

  --accent:           #4fb3a1;
  --accent-hover:     #6cc4b4;
  --accent-active:    #85d1c3;
  --accent-wash:      rgba(79, 179, 161, 0.14);
  --accent-ring:      rgba(79, 179, 161, 0.42);
  --ink-on-accent:    #0f1c19;

  --shadow-card:  0 1px 2px rgba(0,0,0,0.34), 0 1px 3px rgba(0,0,0,0.28);
  --shadow-float: 0 4px 12px rgba(0,0,0,0.48), 0 12px 32px rgba(0,0,0,0.44);

  background-image: url('/img/shoham-circle-background-dark.svg');
}
