/* ==========================================================================
   Universal Service and Parts - design system
   --------------------------------------------------------------------------
   The visual language is technical documentation rather than showroom gloss:
   navy grounds, hairline rules, condensed headings and a monospace face that
   carries every number on the site. Numbers are the product here, so they get
   their own typeface.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Dark grounds */
  --ink: #0a1120;
  --steel: #14203a;
  --steel-raised: #1b2a47;
  --hairline-dark: #26375a;

  /* Light grounds */
  --paper: #ffffff;
  --mist: #f1f4f9;
  --mist-deep: #e4eaf3;
  --hairline: #d3dce9;

  /* Text */
  --text: #0a1120;
  --text-muted: #4a5a75;
  --text-inverse: #eaf0fa;
  --text-inverse-muted: #8fa2c0;

  /* Electric blue: the primary action colour. */
  --arc: #1668f0;
  --arc-bright: #3b87ff;
  --arc-deep: #0d4db8;
  --arc-wash: #e8f0fe;

  /* Restrained orange: reserved for discounts and one accent per view. */
  --signal: #f2610c;
  --signal-ink: #b8460a;
  --signal-wash: #fdeee3;

  /* Status */
  /* 5.0:1 on --ok-wash and 5.8:1 on white. The previous #12855a reached only 4.02:1
     against its own wash, which is where it is nearly always used. */
  --ok: #0f744e;
  --ok-wash: #e1f3eb;
  --warn-ink: #a85b00;
  --warn-wash: #fdf1de;
  --danger: #c02617;
  --danger-wash: #fdeceb;

  /* Type */
  --font-display: "Barlow Condensed", "Arial Narrow", system-ui, sans-serif;
  --font-body: "Barlow", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  --step-2xs: 0.6875rem;
  --step-xs: 0.78125rem;
  --step-sm: 0.875rem;
  --step-base: 1rem;
  --step-md: 1.125rem;
  --step-lg: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);
  --step-xl: clamp(1.5rem, 1.3rem + 1vw, 2rem);
  --step-2xl: clamp(1.875rem, 1.5rem + 1.9vw, 2.75rem);
  --step-3xl: clamp(2.25rem, 1.6rem + 3.2vw, 4rem);

  /* Space */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2rem;
  --space-xl: 3rem;
  --space-2xl: 4.5rem;
  --space-3xl: 6.5rem;

  /* Structure */
  --shell: 78rem;
  --shell-wide: 90rem;
  --radius-sm: 3px;
  --radius: 6px;
  --radius-lg: 10px;

  --shadow-sm: 0 1px 2px rgb(10 17 32 / 0.06), 0 2px 6px rgb(10 17 32 / 0.04);
  --shadow: 0 2px 4px rgb(10 17 32 / 0.06), 0 12px 28px -8px rgb(10 17 32 / 0.14);
  --shadow-lift: 0 4px 8px rgb(10 17 32 / 0.08), 0 22px 48px -12px rgb(10 17 32 / 0.24);

  --header-height: 4.5rem;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --duration: 180ms;
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-height) + 1rem);
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--step-base);
  line-height: 1.6;
  color: var(--text);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: 0.005em;
  text-wrap: balance;
}

h1 { font-size: var(--step-3xl); }
h2 { font-size: var(--step-2xl); }
h3 { font-size: var(--step-xl); }
h4 { font-size: var(--step-lg); }

p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a {
  color: var(--arc);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover { color: var(--arc-deep); }

img, svg { max-width: 100%; height: auto; display: block; }

ul, ol { margin: 0 0 1em; padding-left: 1.25rem; }
ul:last-child, ol:last-child { margin-bottom: 0; }
li { margin-bottom: 0.35em; }

/* Definition lists carry the site's data pairs: spec rails, hero stats, order
   summaries. The UA default indents every dd by 40px, which inside a 120px rail cell
   eats most of the usable width, so it is cleared here rather than per component. */
dl { margin: 0; }
dt { margin: 0; }
dd { margin: 0; }

hr {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: var(--space-lg) 0;
}

button { font: inherit; color: inherit; }

/* Visible focus everywhere. Never removed, only restyled. */
:focus-visible {
  outline: 2px solid var(--arc);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) :focus-visible {
  outline-color: var(--arc-bright);
}

/*
 * Blazor's FocusOnNavigate moves focus to the page heading after each navigation, and
 * the router marks <main> tabindex="-1" for the skip link. Both are announced to screen
 * readers but neither is reachable by Tab, so drawing a focus ring around them only
 * puts an unexplained box around the headline on every page load. Elements a keyboard
 * user can actually reach keep their ring from the rule above.
 */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
  outline: none;
}

::selection {
  background: var(--arc);
  color: #fff;
}

/* --------------------------------------------------------------------------
   3. Accessibility helpers
   -------------------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: 0;
  left: var(--space-sm);
  z-index: 200;
  transform: translateY(-120%);
  padding: 0.7rem 1.1rem;
  background: var(--arc);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--radius) var(--radius);
  text-decoration: none;
  transition: transform var(--duration) var(--ease);
}

.skip-link:focus {
  transform: translateY(0);
  color: #fff;
}

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--space-sm);
}

@media (min-width: 40rem) {
  .shell { padding-inline: var(--space-md); }
}

.shell--wide { max-width: var(--shell-wide); }

.section {
  padding-block: var(--space-2xl);
}

.section--tight { padding-block: var(--space-xl); }

.section--mist { background: var(--mist); }

.section--dark {
  background: var(--ink);
  color: var(--text-inverse);
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) h1,
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) h2,
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) h3,
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) h4 { color: var(--text-inverse); }

/* --arc on a navy ground only reaches 3.8:1; --arc-bright reaches 5.5:1.
   Buttons are excluded: they carry their own ground, so recolouring their text to
   suit the section behind them puts link blue on button blue. Without :not(.btn)
   this rule outranks .btn--primary on specificity and wins. */
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) a:not(.btn) { color: var(--arc-bright); }

/* The blueprint grid. Used behind dark sections at low contrast so it reads as
   drafting paper rather than as decoration. */
.blueprint {
  position: relative;
  isolation: isolate;
}

.blueprint::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(to right, rgb(59 135 255 / 0.07) 1px, transparent 1px),
    linear-gradient(to bottom, rgb(59 135 255 / 0.07) 1px, transparent 1px);
  background-size: 3rem 3rem;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 40%, #000 30%, transparent 78%);
}

.stack > * + * { margin-top: var(--flow, var(--space-sm)); }

.grid {
  display: grid;
  gap: var(--space-md);
}

.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  align-items: center;
}

/* --------------------------------------------------------------------------
   5. Typography components
   -------------------------------------------------------------------------- */

/* The eyebrow is a mono micro-label. It states a category, never a slogan. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-mono);
  font-size: var(--step-2xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--arc);
  margin: 0 0 var(--space-xs);
}

.eyebrow::before {
  content: "";
  width: 1.5rem;
  height: 1px;
  background: currentColor;
  flex: none;
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .eyebrow { color: var(--arc-bright); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.section-head__text { max-width: 46rem; }

.section-head__lede {
  margin-top: var(--space-2xs);
  color: var(--text-muted);
  font-size: var(--step-md);
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .section-head__lede { color: var(--text-inverse-muted); }

.lede {
  font-size: var(--step-md);
  color: var(--text-muted);
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .lede { color: var(--text-inverse-muted); }

.prose { max-width: 44rem; }

.prose h2 {
  margin-top: var(--space-xl);
  margin-bottom: var(--space-xs);
  font-size: var(--step-xl);
}

.prose h3 {
  margin-top: var(--space-lg);
  margin-bottom: var(--space-2xs);
  font-size: var(--step-lg);
}

.prose > :first-child { margin-top: 0; }

.mono {
  font-family: var(--font-mono);
  font-size: var(--step-xs);
  letter-spacing: 0.02em;
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.72rem 1.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color var(--duration) var(--ease),
              border-color var(--duration) var(--ease),
              color var(--duration) var(--ease),
              transform var(--duration) var(--ease);
}

.btn:active { transform: translateY(1px); }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.btn--primary {
  background: var(--arc);
  color: #fff;
  border-color: var(--arc);
}

.btn--primary:hover:not(:disabled) {
  background: var(--arc-deep);
  border-color: var(--arc-deep);
  color: #fff;
}

.btn--secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--hairline);
}

.btn--secondary:hover:not(:disabled) {
  border-color: var(--text);
  background: var(--mist);
  color: var(--text);
}

/* Missing a dark ground here leaves near-black text on navy, which is invisible
   rather than merely low contrast. */
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .btn--secondary {
  color: var(--text-inverse);
  border-color: var(--hairline-dark);
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .btn--secondary:hover:not(:disabled) {
  background: var(--steel-raised);
  border-color: var(--arc-bright);
  color: var(--text-inverse);
}

.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--arc);
  padding-inline: 0.6rem;
}

.btn--ghost:hover:not(:disabled) {
  background: var(--arc-wash);
  color: var(--arc-deep);
}

.btn--danger {
  background: transparent;
  color: var(--danger);
  border-color: transparent;
  padding-inline: 0.6rem;
}

.btn--danger:hover:not(:disabled) { background: var(--danger-wash); }

.btn--sm { padding: 0.5rem 0.95rem; font-size: 0.9375rem; }
.btn--lg { padding: 0.95rem 1.9rem; font-size: 1.1875rem; }
.btn--block { width: 100%; }

/* --------------------------------------------------------------------------
   7. Badges and pills
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--step-2xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.badge--stock { background: var(--ok-wash); color: var(--ok); }
.badge--low { background: var(--warn-wash); color: var(--warn-ink); }
.badge--out { background: var(--mist-deep); color: var(--text-muted); }
.badge--sale { background: var(--signal-wash); color: var(--signal-ink); }
.badge--new { background: var(--arc-wash); color: var(--arc-deep); }

.badge__dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* --------------------------------------------------------------------------
   8. The spec rail - the site's signature element
   --------------------------------------------------------------------------
   A row of hard numbers in mono, split by hairlines. It appears on cards, on
   the product page and in the hero, and it is the one thing that should be
   recognisable across the whole site.
   -------------------------------------------------------------------------- */

.spec-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border-top: 1px solid var(--hairline);
  margin: 0;
  padding: 0;
}

.spec-rail__cell {
  padding: 0.5rem 0.45rem;
  border-left: 1px solid var(--hairline);
  min-width: 0;
}

.spec-rail__cell:first-child {
  border-left: 0;
  padding-left: 0;
}

.spec-rail__label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.1rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * Rail cells are roughly a third of a card, so a long value has to be contained rather
 * than allowed to reflow the rail. Break only where a word genuinely will not fit,
 * cap at two lines, and let the full text through the title attribute and the
 * specification table on the product page.
 */
.spec-rail__value {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: var(--step-xs);
  font-weight: 500;
  color: var(--text);
  line-height: 1.3;
  overflow-wrap: break-word;
}

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .spec-rail, .spec-rail--dark { border-top-color: var(--hairline-dark); }
.spec-rail--dark .spec-rail__cell { border-left-color: var(--hairline-dark); }
.spec-rail--dark .spec-rail__label { color: var(--text-inverse-muted); }
.spec-rail--dark .spec-rail__value { color: var(--text-inverse); }

/* --------------------------------------------------------------------------
   9. Price
   -------------------------------------------------------------------------- */

.price {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  font-family: var(--font-mono);
}

.price__now {
  font-size: var(--step-md);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
}

.price__was {
  font-size: var(--step-xs);
  color: var(--text-muted);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.price--lg .price__now { font-size: var(--step-xl); }
.price--lg .price__was { font-size: var(--step-sm); }

:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .price__now { color: var(--text-inverse); }
:is(.section--dark, .hero, .page-head, .site-footer, .on-dark) .price__was { color: var(--text-inverse-muted); }

/* --------------------------------------------------------------------------
   10. Forms
   -------------------------------------------------------------------------- */

.field { margin-bottom: var(--space-sm); }

.field__label {
  display: block;
  font-family: var(--font-display);
  font-size: var(--step-sm);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text);
  margin-bottom: 0.3rem;
}

.field__hint {
  display: block;
  font-size: var(--step-xs);
  color: var(--text-muted);
  margin-top: 0.25rem;
}

.field__optional {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  text-transform: uppercase;
  margin-left: 0.4rem;
  font-weight: 400;
}

.input,
.select,
.textarea {
  width: 100%;
  padding: 0.65rem 0.8rem;
  font-family: var(--font-body);
  font-size: var(--step-base);
  color: var(--text);
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  transition: border-color var(--duration) var(--ease),
              box-shadow var(--duration) var(--ease);
}

.input::placeholder,
.textarea::placeholder { color: #93a2b8; }

.input:hover,
.select:hover,
.textarea:hover { border-color: #b3c0d3; }

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--arc);
  box-shadow: 0 0 0 3px rgb(22 104 240 / 0.16);
}

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

.select {
  appearance: none;
  padding-right: 2.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%234a5a75' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.8rem center;
  cursor: pointer;
}

/* Blazor applies these classes from EditForm validation state. */
.input.invalid,
.select.invalid,
.textarea.invalid,
.input.modified.invalid,
.textarea.modified.invalid {
  border-color: var(--danger);
  background: var(--danger-wash);
}

.input.modified.valid,
.textarea.modified.valid { border-color: var(--hairline); }

.validation-message,
.field__error {
  display: block;
  margin-top: 0.3rem;
  font-size: var(--step-xs);
  font-weight: 500;
  color: var(--danger);
}

.validation-errors {
  margin: 0 0 var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  list-style: none;
  background: var(--danger-wash);
  border-left: 3px solid var(--danger);
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--danger);
  font-size: var(--step-sm);
}

.checkbox {
  display: flex;
  align-items: start;
  gap: 0.6rem;
  cursor: pointer;
  font-size: var(--step-sm);
}

.checkbox input[type="checkbox"],
.radio input[type="radio"] {
  width: 1.1rem;
  height: 1.1rem;
  margin: 0.18rem 0 0;
  accent-color: var(--arc);
  flex: none;
  cursor: pointer;
}

.radio {
  display: flex;
  align-items: start;
  gap: 0.6rem;
  padding: var(--space-xs);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--duration) var(--ease),
              background-color var(--duration) var(--ease);
}

.radio:hover { border-color: #b3c0d3; background: var(--mist); }

.radio:has(input:checked) {
  border-color: var(--arc);
  background: var(--arc-wash);
}

.radio__title {
  display: block;
  font-weight: 600;
  font-size: var(--step-sm);
}

.radio__note {
  display: block;
  font-size: var(--step-xs);
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   11. Panels, notices and empty states
   -------------------------------------------------------------------------- */

.panel {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
}

.panel--flush { padding: 0; overflow: hidden; }
.panel--mist { background: var(--mist); }

.notice {
  display: flex;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius);
  border-left: 3px solid;
  font-size: var(--step-sm);
}

.notice--info { background: var(--arc-wash); border-color: var(--arc); color: #0c3f96; }
.notice--ok { background: var(--ok-wash); border-color: var(--ok); color: var(--ok); }
.notice--warn { background: var(--warn-wash); border-color: var(--signal); color: var(--warn-ink); }
.notice--error { background: var(--danger-wash); border-color: var(--danger); color: #8e1c11; }

.notice__icon { flex: none; margin-top: 0.15rem; }

.empty-state {
  display: grid;
  place-items: center;
  gap: var(--space-xs);
  padding: var(--space-2xl) var(--space-md);
  text-align: center;
  border: 1px dashed var(--hairline);
  border-radius: var(--radius-lg);
  background: var(--mist);
}

.empty-state__icon { color: var(--text-muted); opacity: 0.7; }

.empty-state__title {
  font-family: var(--font-display);
  font-size: var(--step-lg);
  font-weight: 700;
}

.empty-state__body {
  max-width: 32rem;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   12. Motion
   --------------------------------------------------------------------------
   One reveal, used sparingly on section entry. Everything else is hover state.
   -------------------------------------------------------------------------- */

/*
 * Content is visible by default and is only hidden once the script has confirmed it can
 * actually reveal it again, by putting .js-reveal on the root element. Hiding
 * unconditionally here would mean a script that fails to load leaves most of the page
 * permanently invisible - a decorative animation must never be able to do that.
 */
.reveal {
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}

.js-reveal .reveal:not(.is-visible) {
  opacity: 0;
  transform: translateY(14px);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .js-reveal .reveal:not(.is-visible) {
    opacity: 1;
    transform: none;
  }
}
