/* ============================================================
   Shoemaker Emergency Lighting
   The Switch Panel — a command-vehicle control surface in liquid glass.

   The glass here is a material, not a decoration: every panel is a real
   lens over the photograph behind it, and every light on this page is a
   lamp that exists in one of those photographs.
   ============================================================ */

@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-var.woff2') format('woff2-variations');
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ---------- */
:root {
  /* Ground: wet asphalt and diamond plate at night. Never flat black. */
  --ink:        #0E1013;
  --ink-2:      #161B20;
  --ink-3:      #1C2126;
  --ink-4:      #262D34;

  /* The lamps. Red is the brand mark's own red, sampled from the emblem. */
  --red:        #CB1931;
  --red-hot:    #FF3A52;
  --red-deep:   #8E0F20;
  --amber:      #E28814;
  --amber-hot:  #FFAE3D;

  --paper:      #F2F4F7;
  --paper-dim:  #AEB7C2;
  --paper-low:  #98A3B0;   /* was #7C8794: 3.7:1 on a lit glass panel, failed AA */

  /* Glass: one material, three depths. */
  --glass-1: rgba(255, 255, 255, 0.055);
  --glass-2: rgba(255, 255, 255, 0.085);
  --glass-3: rgba(255, 255, 255, 0.13);
  --glass-edge: rgba(255, 255, 255, 0.34);
  --glass-edge-low: rgba(255, 255, 255, 0.14);

  --blur: 22px;
  --blur-lg: 40px;

  --r-sm: 10px;
  --r:    16px;
  --r-lg: 24px;
  --r-pill: 999px;

  /* Detent. Everything that moves uses this or the slow variant. */
  --ease: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --detent: 200ms var(--ease);
  --slow: 620ms var(--ease);
  /* Panels that grow out of a control (the Let's chat panel): a drawer curve
     for the morph, a strong ease-out for what enters inside it. */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);

  --measure: 68ch;
  --gut: clamp(1.15rem, 4vw, 2.75rem);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  background: #0E1013;   /* the rubber-band area on iOS paints THIS, not body */
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--ink);
  color: var(--paper);
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* ---------- browser surfaces: these ship with the design, not with the browser ---------- */
::selection { background: var(--red); color: #fff; }
::-moz-selection { background: var(--red); color: #fff; }

:focus-visible {
  outline: 2px solid var(--amber-hot);
  outline-offset: 3px;
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

* { scrollbar-width: thin; scrollbar-color: var(--ink-4) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--ink); }
::-webkit-scrollbar-thumb {
  background: var(--ink-4);
  border-radius: var(--r-pill);
  border: 3px solid var(--ink);
}
::-webkit-scrollbar-thumb:hover { background: #38424c; }

a { color: var(--paper); text-decoration-color: rgba(203, 25, 49, 0.85); text-underline-offset: 0.22em; text-decoration-thickness: 1.5px; }
a:hover { text-decoration-color: var(--red-hot); }

/* ---------- type ---------- */
.display, h1, h2, h3, .legend, .plate {
  font-family: 'Archivo', 'Archivo Expanded', system-ui, sans-serif;
  font-synthesis: none;
}

h1, .h1 {
  font-size: clamp(2.1rem, 7.2vw, 4.6rem);
  font-weight: 800;
  font-stretch: 118%;
  line-height: 0.97;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
h2, .h2 {
  font-size: clamp(1.65rem, 4.4vw, 3rem);
  font-weight: 700;
  font-stretch: 112%;
  line-height: 1.04;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
h3, .h3 {
  font-size: clamp(1.12rem, 2.2vw, 1.4rem);
  font-weight: 700;
  font-stretch: 105%;
  line-height: 1.22;
  letter-spacing: -0.012em;
}

p { max-width: var(--measure); }
.lede { font-size: clamp(1.03rem, 2.1vw, 1.26rem); line-height: 1.55; color: #D6DCE4; }
.dim { color: var(--paper-dim); }

/* The engraved legend plate on a real switch: condensed caps, cut into metal. */
/* impeccable-disable all-caps-body: an engraved switch legend plate is the
   committed world here, not a styling default. These are labels on a control
   surface, never running prose. */
.legend {
  font-weight: 700;
  font-stretch: 78%;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.74rem;
  line-height: 1;
}

/* ---------- layout ---------- */
.wrap { width: min(1220px, 100% - (var(--gut) * 2)); margin-inline: auto; }
.wrap-narrow { width: min(760px, 100% - (var(--gut) * 2)); margin-inline: auto; }
.section { padding-block: clamp(2.6rem, 5.6vw, 4.6rem); position: relative; }

/* ---------- the glass material ----------
   One material. The top edge catches light because a real bevel does.  */
.glass {
  position: relative;
  background:
    linear-gradient(180deg, var(--glass-3) 0%, var(--glass-1) 42%, rgba(255,255,255,0.03) 100%);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(165%);
  backdrop-filter: blur(var(--blur)) saturate(165%);
  border: 1px solid var(--glass-edge-low);
  border-top-color: var(--glass-edge);
  border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    inset 0 -1px 0 rgba(0, 0, 0, 0.35),
    0 26px 64px -26px rgba(0, 0, 0, 0.85),
    0 4px 14px -6px rgba(0, 0, 0, 0.55);
}
/* the specular sweep across a curved lens */
.glass::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(104deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 32%, rgba(255,255,255,0) 68%, rgba(255,255,255,0.055) 100%);
  pointer-events: none;
}

/* ---------- the switch panel ---------- */
.panel {
  padding: clamp(1rem, 2.6vw, 1.6rem);
  border-radius: var(--r-lg);
}

.panel-plate {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.75rem 0.85rem;
  border-bottom: 1px solid rgba(255,255,255,0.1);
  margin-bottom: clamp(0.85rem, 2vw, 1.15rem);
}
.panel-plate img { width: 34px; height: 34px; border-radius: var(--r-xs); flex: none; }
.panel-plate .legend { color: var(--paper-dim); }

.bank {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
}


/* A rocker switch. It travels, it detents, its legend backlights. */
.sw {
  --lamp: var(--red);
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.72rem;
  min-height: 56px;
  padding: 0.62rem 0.8rem;
  border-radius: var(--r);
  background: linear-gradient(180deg, rgba(255,255,255,0.075), rgba(255,255,255,0.02));
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.16), 0 2px 8px -3px rgba(0,0,0,0.7);
  color: var(--paper);
  text-decoration: none;
  cursor: pointer;
  text-align: left;
  width: 100%;
  transition: transform var(--detent), box-shadow var(--detent), background var(--detent), border-color var(--detent);
  will-change: transform;
}
.sw:hover { background: linear-gradient(180deg, rgba(255,255,255,0.11), rgba(255,255,255,0.04)); border-color: rgba(255,255,255,0.2); }
.sw:active { transform: translateY(1.5px) scale(0.994); box-shadow: inset 0 2px 5px rgba(0,0,0,0.5); }

/* A rocker is a paddle on a pivot, seated in a recessed bezel. Its two faces
   catch light differently, and throwing it INVERTS which face is lit — so the
   thrown state is readable with the lamp covered. The lamp confirms; it does
   not carry the state on its own. */
.sw-rocker {
  flex: none;
  width: 30px; height: 40px;
  border-radius: 7px;
  padding: 3px;
  background: linear-gradient(180deg, #080A0C 0%, #14181C 100%);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.06),
    0 1px 0 rgba(255, 255, 255, 0.07);
  perspective: 150px;
}

.sw-paddle {
  display: block;
  width: 100%; height: 100%;
  border-radius: 4px;
  position: relative;
  transform-origin: 50% 50%;
  transform: rotateX(15deg);
  /* the hard seam at 50% IS the pivot line */
  background: linear-gradient(180deg,
    #58626C 0%, #434D57 47%,
    #1F252B 50%, #141A1F 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.34), 0 1px 2px rgba(0,0,0,0.6);
  transition: transform var(--detent), background var(--detent), box-shadow var(--detent);
  will-change: transform;
}

/* thrown: the paddle rocks the other way and the faces swap. */
.sw[aria-pressed="true"] .sw-paddle,
.sw.is-on .sw-paddle {
  transform: rotateX(-17deg);
  background: linear-gradient(180deg,
    #141A1F 0%, #1F252B 47%,
    #434D57 50%, #5E6873 100%);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.3), inset 0 2px 4px rgba(0,0,0,0.65);
}

/* the lamp: a lens set into the paddle's lower face */
.sw-paddle::after {
  content: '';
  position: absolute;
  left: 50%; bottom: 4px;
  width: 6px; height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: #0A0D10;
  box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.95);
  transition: background var(--detent), box-shadow var(--detent);
}
.sw[aria-pressed="true"] .sw-paddle::after,
.sw.is-on .sw-paddle::after {
  background: var(--lamp);
  /* impeccable-disable dark-glow: an energised indicator lamp. */
  box-shadow: 0 0 8px 1px var(--lamp), inset 0 0 2px rgba(255, 255, 255, 0.7);
}

/* where you ARE is a quieter signal than what you THREW */
.sw.is-current { border-color: rgba(255,255,255,0.26); }

.sw-text { min-width: 0; }
.sw-text .legend { display: block; color: var(--paper-dim); transition: color var(--detent), text-shadow var(--detent); }
.sw[aria-pressed="true"] .sw-text .legend,
.sw.is-on .sw-text .legend { color: #fff; text-shadow: 0 0 12px var(--lamp); }
.sw-sub { display: block; font-size: 0.76rem; color: var(--paper-low); margin-top: 0.2rem; line-height: 1.3; }

.sw[data-lamp="amber"] { --lamp: var(--amber-hot); }
.sw[data-lamp="white"] { --lamp: #DCE6F2; }

/* ---------- actions ---------- */
.rail {
  display: flex;
  gap: 0.6rem;
  margin-top: clamp(0.9rem, 2vw, 1.2rem);
  padding-top: clamp(0.9rem, 2vw, 1.15rem);
  border-top: 1px solid rgba(255,255,255,0.1);
}
@media (max-width: 430px) { .rail { flex-direction: column; } }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 52px;
  padding: 0 1.3rem;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-weight: 650;
  font-size: 0.92rem;
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  flex: 1;
  transition: transform var(--detent), box-shadow var(--detent), background var(--detent);
  will-change: transform;
}
.btn:active { transform: translateY(1px) scale(0.99); }

.btn-lamp {
  /* #CB1931 -> #A11226 keeps white at 5.6:1 top and 8.0:1 bottom. The
     brighter #FF3A52 read at 3.5:1 and failed AA. */
  background: linear-gradient(180deg, var(--red) 0%, #A11226 100%);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 10px 26px -12px rgba(0,0,0,0.85), 0 2px 6px -2px rgba(0,0,0,0.6);
}
.btn-lamp:hover { background: linear-gradient(180deg, #D91C37 0%, #AE1429 100%); box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 14px 30px -12px rgba(0,0,0,0.9); }

.btn-glass {
  background: rgba(255,255,255,0.075);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
  border-color: rgba(255,255,255,0.2);
  color: var(--paper);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.2);
}
.btn-glass:hover { background: rgba(255,255,255,0.13); border-color: rgba(255,255,255,0.3); }

/* ---------- focus resolves legibility (the glass reveal) ---------- */
/* Scoped to .js on purpose. Without scripting the content is simply THERE:
   an entrance animation must never be the thing that makes copy exist. */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(9px);
  transition: opacity var(--slow), transform var(--slow), filter var(--slow);
  will-change: transform, opacity, filter;
}
.js .reveal.in { opacity: 1; transform: none; filter: blur(0); }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; filter: none; transition: none; }
}

/* ---------- header ---------- */
.hdr {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  padding: calc(var(--safe-t) + 0.55rem) var(--gut) 0.55rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  transition: background var(--detent), box-shadow var(--detent), -webkit-backdrop-filter var(--detent), backdrop-filter var(--detent);
}
.hdr.stuck {
  transform: translateZ(0);
  background: rgba(14, 16, 19, 0.72);
  -webkit-backdrop-filter: blur(20px) saturate(165%);
  backdrop-filter: blur(20px) saturate(165%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.08), 0 10px 30px -18px rgba(0,0,0,0.9);
}
.hdr-mark { display: flex; align-items: center; gap: 0.6rem; text-decoration: none; flex: none; }
.hdr-mark img { width: 38px; height: 38px; border-radius: var(--r-xs); }
.hdr-mark .legend { color: var(--paper); font-size: 0.74rem; line-height: 1.25; max-width: 9em; }
.hdr nav { margin-left: auto; display: flex; gap: 0.2rem; align-items: center; }
.hdr nav a {
  padding: 0.72rem 0.8rem;   /* 44px minimum target */
  border-radius: var(--r-sm);
  text-decoration: none;
  font-size: 0.86rem;
  font-weight: 560;
  color: var(--paper-dim);
  transition: color var(--detent), background var(--detent);
}
.hdr nav a:hover, .hdr nav a[aria-current="page"] { color: #fff; background: rgba(255,255,255,0.08); }
@media (max-width: 680px) { .hdr nav .nav-full { display: none; } }
/* Feniex, TigerTough and Contact need 459px beside the wordmark; a phone has
   360-430. The wordmark already wraps to three words, so its box shrinks to the
   longest one, and below 430px Contact leaves the header: the call bar under
   the thumb carries Call and Let's chat on every phone page. */
@media (max-width: 560px) {
  .hdr { gap: 0.6rem; }
  .hdr-mark .legend { width: min-content; }
  .hdr nav a { padding-inline: 0.55rem; }
}
@media (max-width: 430px) { .hdr nav a[href="contact.html"] { display: none; } }
@media (max-width: 370px) { .hdr { gap: 0.45rem; } .hdr nav a { padding-inline: 0.42rem; } }

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: calc(var(--safe-t) + 5.2rem) var(--gut) calc(var(--safe-b) + 3rem);
  min-height: 100svh;
  isolation: isolate;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; z-index: -2; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 52% 42%; }
/* the night grade: darken toward the edges so the lamps read as the only light */
.hero-media::after {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 85% at 50% 58%, rgba(14,16,19,0) 0%, rgba(14,16,19,0.42) 52%, rgba(14,16,19,0.9) 100%),
    linear-gradient(180deg, rgba(14,16,19,0.82) 0%, rgba(14,16,19,0.18) 26%, rgba(14,16,19,0.55) 76%, var(--ink) 100%);
}
#lens { position: absolute; inset: 0; z-index: -1; pointer-events: none; }

.hero-panel {
  width: min(560px, 100%);
  /* No opaque scrim. The darkening lives in the backdrop filter where it can
     be undone locally, and contrast() restores the local variance that
     brightness() takes out, so the photograph behind the glass keeps its
     edges instead of flattening to a grey field. */
  background: linear-gradient(180deg, var(--glass-3) 0%, var(--glass-1) 42%, rgba(255,255,255,0.03) 100%);
  -webkit-backdrop-filter: blur(20px) saturate(150%) brightness(0.46) contrast(1.42);
  backdrop-filter: blur(20px) saturate(150%) brightness(0.46) contrast(1.42);
}
/* The type occupies the upper-left. Everywhere else has no reason to be dark,
   and that is exactly where the vehicle should read through the glass. */
.hero-panel::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(168deg, rgba(8,10,13,0.5) 0%, rgba(8,10,13,0.34) 46%, rgba(8,10,13,0) 78%);
}
.hero-panel > * { position: relative; z-index: 1; }
.hero h1 { margin-bottom: 0.7rem; }
.hero .lede { margin-bottom: clamp(1rem, 2.4vw, 1.4rem); }

/* ---------- sections that a switch energises ---------- */
.circuit { position: relative; }
.circuit::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--lamp, var(--red)), transparent);
  opacity: 0.45;
}
.circuit.live { --glow: 1; }
.circuit.live::after {
  content: '';
  position: absolute;
  inset: -1px 0 auto 0;
  height: 190px;
  background: radial-gradient(70% 100% at 50% 0%, color-mix(in srgb, var(--lamp, var(--red)) 26%, transparent) 0%, transparent 72%);
  pointer-events: none;
  opacity: 0;
  animation: energise 1500ms var(--ease) forwards;
}
@keyframes energise { 0% { opacity: 0; } 22% { opacity: 1; } 100% { opacity: 0.32; } }
@media (prefers-reduced-motion: reduce) { .circuit.live::after { animation: none; opacity: 0.3; } }

/* ---------- spec rows: measurement honesty, never adjectives ---------- */
.specs { display: grid; gap: 1px; background: rgba(255,255,255,0.09); border-radius: var(--r); overflow: hidden; }
.spec {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1rem;
  align-items: baseline;
  padding: 0.95rem 1.15rem;
  background: var(--ink-2);
}
.spec dt { font-weight: 600; }
.spec dd { color: var(--paper-dim); font-variant-numeric: tabular-nums; text-align: right; }

/* ---------- work: the proof ---------- */
.work { display: grid; gap: clamp(1rem, 2.2vw, 1.5rem); grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.job {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink-2);
  border: 1px solid rgba(255,255,255,0.08);
}
.job img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform var(--slow); }
.job:hover img { transform: scale(1.035); }
.job-body { padding: 1.05rem 1.15rem 1.25rem; }
.job-body p { font-size: 0.92rem; color: var(--paper-dim); margin-top: 0.4rem; }

/* ---------- reviews ---------- */
.stars { display: inline-flex; gap: 2px; color: var(--amber-hot); }
.stars svg { width: 15px; height: 15px; }
.review { padding: 1.25rem 1.35rem; border-radius: var(--r-lg); }
.review p { font-size: 0.92rem; color: #D6DCE4; margin-block: 0.7rem; }
.review cite { font-style: normal; font-weight: 650; font-size: 0.92rem; }

/* ---------- footer ---------- */
.ftr { border-top: 1px solid rgba(255,255,255,0.1); background: var(--ink-2); padding-bottom: calc(var(--safe-b) + 2rem); }
.ftr a { color: var(--paper-dim); text-decoration: none; }
.ftr a:hover { color: #fff; }
.ftr dl { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 1.2rem; font-size: 0.92rem; }
.ftr dt { color: var(--paper-low); }
.ftr dd { color: var(--paper-dim); font-variant-numeric: tabular-nums; }
/* the shop email is one 36-character word; unbroken it widened every page below 362px */
.ftr dl { grid-template-columns: auto minmax(0, 1fr); }
.ftr dd { overflow-wrap: anywhere; }

/* ---------- mobile call bar: a chief with a dead light bar wants the number ---------- */
.callbar {
  transform: translateZ(0);
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 70;
  display: none;
  gap: 0.5rem;
  padding: 0.55rem calc(var(--gut) * 0.6) calc(var(--safe-b) + 0.55rem);
  background: rgba(14, 16, 19, 0.82);
  -webkit-backdrop-filter: blur(22px) saturate(170%);
  backdrop-filter: blur(22px) saturate(170%);
  border-top: 1px solid rgba(255,255,255,0.12);
}
@media (max-width: 860px) { .callbar { display: flex; } body { padding-bottom: 76px; } }
.callbar .btn { min-height: 48px; font-size: 0.92rem; }

.icon { width: 18px; height: 18px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.skip {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--red); color: #fff; padding: 0.7rem 1.1rem;
  border-radius: 0 0 var(--r-sm) 0; z-index: 200;
}
.skip:focus {
  width: auto; height: auto;
  overflow: visible;
  clip-path: none;
  left: 0; top: calc(var(--safe-t) + 0px);
}

/* The call bar is fixed over the page, so the hero owes it clearance. */
@media (max-width: 860px) {
  .hero { padding-bottom: calc(var(--safe-b) + 84px); }
}

/* ---------- phones ----------
   These live at the end of the sheet on purpose: they override the base
   component rules above, which share their specificity. */
@media (max-width: 480px) {
  .bank { gap: 0.45rem; }
  .sw { min-height: 52px; padding: 0.5rem 0.62rem; gap: 0.55rem; }
  .sw-rocker { width: 28px; height: 28px; border-radius: 7px; }
  .sw-sub { display: none; }
  .sw-text .legend { font-size: 0.72rem; letter-spacing: 0.09em; }
}

/* On a phone the fixed call bar already carries both actions, so the panel's
   own rail would be the same two buttons twice on one screen. */
@media (max-width: 860px) {
  .hero-panel .rail { display: none; }
}

/* A .rail always owns the space under its own rule, even where a page
   turns the border off for a centred variant. */
.rail > * { margin-top: 0; }

/* A lens with content pressed against its bevel looks like a mistake. Any
   .glass gets a floor; .panel and inline padding still override it. */
.glass { padding: clamp(1rem, 2.4vw, 1.5rem); }

/* ---------- footer touch targets ----------
   An 18px social glyph and a 17px-tall phone link are fine to look at and
   impossible to hit with a gloved thumb. The hit area grows to 44px; the
   negative margin keeps the visual layout exactly where it was. */
.ftr p a[aria-label] {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -13px;          /* 44 - 18 = 26, halved */
  border-radius: var(--r-sm);
  transition: background var(--detent), color var(--detent);
}
.ftr p a[aria-label]:hover { background: rgba(255,255,255,0.09); }
.ftr p { display: flex; gap: 1.55rem; align-items: center; }

.ftr dd a,
.ftr a:not([aria-label]):not(.hdr-mark) {
  display: inline-block;
  padding-block: 0.7rem;
  margin-block: -0.7rem;
}

/* ---------- the hero headline is sized by its PANEL, not the viewport ----------
   The global h1 scale is tuned for a full-width container. Inside the switch
   panel the usable measure is capped at ~510px, so a 74px display face could
   not fit "Emergency" on one line and spilled 136px past its own box at
   1024px and wider. This clamp tops out where the panel can actually hold it. */
.hero-panel h1 {
  font-size: clamp(1.95rem, 4.5vw, 3.35rem);
  font-stretch: 112%;
  letter-spacing: -0.025em;
  line-height: 1.0;
  overflow-wrap: break-word;
}

/* ---------- anchor targets clear the fixed header ----------
   Throwing a switch scrolls to its circuit. Without this the heading lands
   underneath the header and the user sees the middle of a section instead of
   its start. The value is the header's real height plus the notch inset. */

/* A heading wants air under the header, not a hairline. */
section[id], [id][data-circuit-section] { scroll-margin-top: calc(var(--safe-t) + 96px); }
@media (max-width: 480px) {
  section[id], [id][data-circuit-section] { scroll-margin-top: calc(var(--safe-t) + 84px); }
}

/* iOS has no hover, so every control needs a real pressed state. */
@media (hover: none) {
  .sw:active  { background: linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0.05)); }
  .job:active { transform: scale(0.992); transition: transform 120ms var(--ease); }
  .ftr a:active, .hdr nav a:active { color: #fff; }
}

/* Form fields must never trigger the iOS zoom-on-focus, which fires below 16px. */
input, textarea, select { font-size: max(16px, 1rem); }

/* The wordmark beside the emblem reads as three stacked words on a phone and
   as two on anything wider, where there is room for it. */
@media (min-width: 681px) {
  .hdr-mark .legend { max-width: none; white-space: nowrap; font-size: 0.7rem; letter-spacing: 0.12em; }
}

/* ---------- commit the red, give amber a job, add the second ground ----------
   OWN-WORLD asked for red at page scale as fields and named two gunmetal
   planes. The build shipped one near-black plane with red as an accent, which
   is the one thing the direction explicitly refused. */
.section--alt { background: var(--ink-3); }

.section--lamp {
  background:
    radial-gradient(120% 120% at 50% 0%, #D91C37 0%, var(--red) 46%, #8E0F20 100%);
  color: #fff;
}
.section--lamp .lede,
.section--lamp p { color: rgba(255, 255, 255, 0.93); }
.section--lamp .btn-glass {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.45);
  color: #fff;
}
.section--lamp .btn-glass:hover { background: rgba(255, 255, 255, 0.26); }
.section--lamp .btn-lamp {
  background: #fff;
  color: var(--red-deep);
  box-shadow: 0 10px 26px -12px rgba(0, 0, 0, 0.6);
}

/* Amber is the ARMED state the contract named, not a focus ring colour. */
.sw[data-lamp="amber"].is-on { border-color: rgba(255, 174, 61, 0.42); }
.sw[data-lamp="amber"].is-on .sw-text .legend { text-shadow: 0 0 12px var(--amber-hot); }

/* A required mark is a note to the reader, not an alarm. Red is this brand's
   lamp colour and spending it on form chrome devalues it where it matters. */
.req {
  margin-left: 0.5rem;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-low);
  font-weight: 600;
}
form label { display: block; margin-bottom: 0.38rem; font-weight: 600; }

/* ---------- rhythm ----------
   Uniform padding on both edges of every section means adjacent sections each
   contribute, so a 120px value produced a 240px band between every block and
   2,640px of pure padding down the page. Spacing now comes from the
   relationship between blocks: tight inside a run that shares a subject, open
   only where the subject actually changes. */

/* The three service sections are one sequence, not three arrivals. */
.section--run { padding-block: clamp(1.6rem, 3.2vw, 2.6rem); }
.section--run + .section--run { padding-top: 0; }

/* A section that owns a coloured field needs the room the colour asks for. */
.section--lamp, .section--alt { padding-block: clamp(3rem, 6.2vw, 5.2rem); }

/* A heading owns the block beneath it; the gap above it is what separates
   subjects, so it is always larger than the gap below. */
.section > .wrap > h2,
.section > .wrap-narrow > h2 { margin-bottom: 0.55rem; }

/* Story and owner are one subject. Give their prose one measure and one
   alignment so the two blocks read as a system rather than as two decisions. */
#story .wrap > *, #owner .wrap > * { text-align: left; }
#story p, #owner p { max-width: 62ch; }
#story + #owner { padding-top: clamp(1.4rem, 3vw, 2.4rem); }

/* ---------- extracted from repeated inline styles ----------
   These patterns were duplicated across pages as inline attributes, which put
   them outside the system: a change had to be made in six files and a drift
   detector could not see them as tokens. */

/* the recessed metal tile behind a capability icon */
.tile {
  width: 40px; height: 40px;
  flex: none;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, #3A434C, #20262C);
  border: 1px solid rgba(0, 0, 0, 0.55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), inset 0 -2px 4px rgba(0, 0, 0, 0.5);
  color: var(--amber-hot);
}

/* the lightbox shell and its dismiss control */
.lb {
  position: fixed; inset: 0; z-index: 200; margin: 0;
  background: rgba(8, 9, 11, 0.93);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  display: grid; place-items: center;
  padding: var(--gut);
}
.lb-close {
  position: absolute;
  top: calc(var(--safe-t) + 1rem); right: 1rem;
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff; cursor: pointer;
  display: grid; place-items: center;
}
.lb img { max-width: min(1100px, 100%); max-height: 78dvh; object-fit: contain; border-radius: var(--r); }

/* the two small type steps, so they stop being inline one-offs */
.t-sm { font-size: 0.86rem; }
.t-md { font-size: 0.92rem; }

/* the two rhythm steps that were inline on 38 elements */
.mt-1 { margin-top: 0.7rem; }
.mt-2 { margin-top: 0.8rem; }

/* ---------- the owner's temporary notice ----------
   Sits under the fixed header on every page when he has one running, and
   takes itself down on the date he set. Amber rather than red: red is the
   brand's own lamp and spending it on a routine message devalues it. */
.sitenotice {
  position: relative;
  z-index: 50;
  margin-top: calc(var(--safe-t) + 62px);
  background: linear-gradient(180deg, #E28814, #C4740E);
  color: #17120A;
  font-weight: 650;
  font-size: .94rem;
  padding: .7rem 0;
  text-align: center;
}
.sitenotice + main .hero { margin-top: calc(-1 * (var(--safe-t) + 62px)); }
@media (max-width: 480px) { .sitenotice { font-size: .88rem; padding: .62rem 0; } }

/* ---------- the Feniex teaser on the home route ----------
   A small piece of the catalogue's bench: the flagship lit, standing on a
   horizon with the pool its own light throws. It links to the bench itself. */
.fx-teaser { overflow: hidden; }
.fx-grid {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  align-items: center;
}
.fx-bench {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: end center;
  aspect-ratio: 16 / 9;
  /* padding resolves against WIDTH: 28% of a 16:9 height is 15.75% of its width */
  padding: 0 4% 15.75%;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: linear-gradient(180deg, #12161A 0%, #171C21 72%, #1E242A 72%, #12161A 100%);
}
.fx-bench::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(50% 24% at 50% 72%, rgba(255, 42, 61, 0.38), transparent);
}
.fx-bench img { width: 100%; height: auto; transition: transform var(--slow); }
.fx-bench:hover img { transform: translateY(-4px); }

/* ---------- the TigerTough teaser on the home route ----------
   The photograph leads on the left so it does not echo the Feniex block above. */
.tt-teaser img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 40% 55%;
  border-radius: var(--r-lg);
}

/* ---------- form fields ----------
   Shared by the contact page and the Let's chat panel. */
.qf-field { display: grid; gap: 0.4rem; }
.qf-field > label { font-weight: 600; font-size: 0.92rem; }
.qf-hint  { font-size: 0.86rem; color: var(--paper-low); max-width: none; }

/* The field is the same lens as the panel, one depth shallower: translucent
   body, a lit top edge where a real bevel would catch the cab light. */
.qf-input {
  width: 100%;
  min-height: 52px;
  padding: 0.82rem 1rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-top-color: rgba(255, 255, 255, 0.34);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), inset 0 -1px 0 rgba(0, 0, 0, 0.3);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
  color: var(--paper);
  appearance: none;
  transition: background var(--detent), border-color var(--detent), box-shadow var(--detent);
}
.qf-input::placeholder { color: var(--paper-low); }
.qf-input:hover { background: rgba(255, 255, 255, 0.085); border-color: rgba(255, 255, 255, 0.22); }
textarea.qf-input { min-height: 150px; line-height: 1.55; resize: vertical; }

/* A field the visitor has actually left in a bad state reads red. Untouched
   required fields stay neutral, which is why this is :user-invalid. */
.qf-input:user-invalid {
  border-color: var(--red-hot);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 0 0 1px rgba(255, 58, 82, 0.4);
}
.qf-pot{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ---------- Let's chat ----------
   A brand-red capsule that GROWS into the panel: the panel is clipped to the
   button's own rectangle and opens out of it, and a red skin over the panel
   dissolves as it grows, so the capsule and the panel read as one surface.
   The motion itself is in js/chat.js (it has to measure the button). */
html:not(.js) .chat { display: none; }

.chat-fab {
  position: fixed;
  right: calc(var(--safe-r) + 22px);
  bottom: calc(var(--safe-b) + 22px);
  z-index: 80;
  display: inline-flex;
  align-items: center;
  gap: 0.62rem;
  min-height: 56px;
  padding: 0 1.4rem 0 0.5rem;
  border: 0;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--red) 0%, #A11226 100%);
  color: #fff;
  font-family: 'Archivo', system-ui, sans-serif;
  font-synthesis: none;
  font-weight: 700;
  font-stretch: 104%;
  font-size: 1rem;
  letter-spacing: -0.005em;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 14px 32px -12px rgba(0, 0, 0, 0.85), 0 3px 8px -2px rgba(0, 0, 0, 0.6);
  cursor: pointer;
  transition: transform 160ms var(--ease-out-strong), box-shadow var(--detent), background var(--detent);
}
.chat-fab img {
  width: 40px;
  height: 40px;
  border-radius: var(--r-sm);
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.85), 0 2px 6px rgba(0, 0, 0, 0.45);
}
.chat-fab:active { transform: scale(0.97); }
/* Out of the way while the panel is out. Coming back it appears instantly:
   the panel has just folded into its exact shape, so a fade would flicker. */
.chat:not([data-state="closed"]) .chat-fab {
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 140ms var(--ease-out-strong), transform 140ms var(--ease-out-strong);
}
.chat[data-state="open"] .chat-fab { pointer-events: none; }
/* Folding back, the capsule rises above the panel and fades in as it lands,
   so its label arrives with it instead of popping in after. */
.chat[data-state="closing"] .chat-fab { z-index: 95; }
/* Changed your mind while it folds away? The folding panel lets the click
   through to the capsule underneath, which opens it again from mid-fold. */
.chat[data-state="closing"] .chat-panel { pointer-events: none; }
@media (hover: hover) and (pointer: fine) {
  .chat-fab:hover {
    background: linear-gradient(180deg, #D91C37 0%, #AE1429 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 18px 36px -12px rgba(0, 0, 0, 0.9), 0 3px 8px -2px rgba(0, 0, 0, 0.6);
  }
}

.chat-panel {
  position: fixed;
  right: calc(var(--safe-r) + 16px);
  bottom: calc(var(--safe-b) + 16px);
  z-index: 90;
  width: min(400px, calc(100vw - 32px));
  max-height: min(720px, calc(100dvh - var(--safe-t) - 32px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(36, 42, 48, 0.88) 0%, rgba(18, 22, 26, 0.93) 100%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-top-color: rgba(255, 255, 255, 0.34);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 30px 70px -24px rgba(0, 0, 0, 0.9), 0 6px 18px -6px rgba(0, 0, 0, 0.6);
}
/* the capsule's red, laid over the panel while it grows, then dissolved */
.chat-skin {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(180deg, var(--red) 0%, #A11226 100%);
}
.chat-body {
  position: relative;
  z-index: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.85rem 1.2rem 1.25rem;
}

.chat-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding-bottom: 0.75rem;
  margin-bottom: 0.95rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.chat-head img { width: 34px; height: 34px; border-radius: var(--r-sm); }
.chat-head .legend { flex: 1; color: var(--paper-dim); }
.chat-x {
  width: 44px;
  height: 44px;
  margin: -6px -10px -6px 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--paper-dim);
  cursor: pointer;
  transition: background var(--detent), color var(--detent);
}
@media (hover: hover) and (pointer: fine) {
  .chat-x:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }
}

/* form and confirmation share one cell, so the panel never changes size */
.chat-stage { display: grid; }
.chat-stage > * { grid-area: 1 / 1; }

.chat-form { display: grid; gap: 0.85rem; align-content: start; }
.chat-form h2, .chat-done h2 { font-size: clamp(1.5rem, 3vw, 1.85rem); }
.chat-lede { margin-top: -0.4rem; font-size: 0.92rem; color: var(--paper-dim); }
.chat-about {
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.62rem 0.85rem;
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.28);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.55);
  font-size: 0.92rem;
  font-weight: 600;
}
.chat-about .legend { flex: none; color: var(--paper-low); }
.chat-panel textarea.qf-input { min-height: 100px; }
.chat-send { display: flex; align-items: center; gap: 0.6rem 1.1rem; flex-wrap: wrap; margin-top: 0.15rem; }
.chat-send .btn { flex: 0 0 auto; padding-inline: 2.1rem; }
.chat-send a { font-size: 0.92rem; color: var(--paper-dim); }
.chat-form[aria-busy="true"] .btn { opacity: 0.72; cursor: progress; }
.chat-error { font-size: 0.92rem; color: #FFD3D9; }

/* what enters inside the panel, after it has started to open */
.chat-in {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 220ms var(--ease-out-strong), transform 220ms var(--ease-out-strong);
}
.chat[data-state="open"] .chat-in {
  opacity: 1;
  transform: none;
  transition-delay: calc(110ms + var(--i, 0) * 40ms);
}
.chat[data-state="closing"] .chat-in { transition-duration: 90ms; }

/* Sent: the form steps back and the site's own rocker throws, lamp lit. */
.chat-form.is-leaving { opacity: 0; transition: opacity 160ms var(--ease-out-strong); }
.chat-form.is-gone { visibility: hidden; }
.chat-done {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0.7rem;
  padding: 1rem 0;
  text-align: center;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 240ms var(--ease-out-strong) 80ms, transform 240ms var(--ease-out-strong) 80ms;
}
.chat-done.is-in { opacity: 1; transform: none; }
.chat-done h2:focus { outline: none; }
.chat-done p { color: var(--paper-dim); }
.chat-done .btn { flex: 0 0 auto; margin-top: 0.4rem; padding-inline: 2.1rem; }
.chat-sw,
.chat-sw:hover {
  width: auto;
  min-height: 0;
  margin: 0.4rem 0 1rem;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  cursor: default;
}
.chat-sw .sw-rocker { transform: scale(1.7); }

/* On a phone the panel is a sheet over a dimmed page */
.chat-scrim {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: rgba(8, 9, 11, 0.6);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 260ms var(--ease-out-strong);
}
.chat[data-state="open"] .chat-scrim { opacity: 1; }
@media (min-width: 861px) { .chat-scrim { display: none !important; } }

/* Below 860px the call bar carries the trigger, so no capsule floats over it. */
@media (max-width: 860px) {
  .chat-fab { display: none; }
  .chat-panel {
    left: calc(var(--safe-l) + 8px);
    right: calc(var(--safe-r) + 8px);
    bottom: calc(var(--safe-b) + 8px);
    width: auto;
    max-height: calc(100dvh - var(--safe-t) - 24px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-in, .chat-done { transform: none; }
  .chat[data-state="open"] .chat-in { transition-delay: 0ms; }
}

/* ---------- the hero rockers, in three dimensions ----------
   js/rockers.js draws a real rocker over each slot once WebGL is up and adds
   .rockers-3d; until then (or without WebGL) the CSS rockers below stand. */
.hero .sw-rocker { width: 40px; height: 54px; }
.bank { position: relative; }
.bank > .rockers {
  position: absolute;
  left: -18px;
  top: -18px;
  z-index: 2;
  pointer-events: none;
}
.bank.rockers-3d .sw-rocker { background: none; box-shadow: none; }
.bank.rockers-3d .sw-paddle { visibility: hidden; }
/* the 3D paddle presses in on its own; the tile must not slide out from under it */
.bank.rockers-3d .sw:active { transform: none; }
@media (max-width: 480px) {
  .hero .sw-rocker { width: 31px; height: 42px; }
}
