/* ==========================================================================
   Blue Line Crafts — stylesheet
   Dark theme, blue accent. All colors are custom properties in :root, so
   retheming the whole site is a single-block edit.

   Every blue below is derived from the logo: hue 222, saturation 100%, with
   only the lightness varied. Sampled from BLC Logo 3.png, where the
   dominant blue is #0046E6.

   Why more than one blue: #0046E6 scores 7.23:1 with white on top, so it is
   a good button fill, but only 2.69:1 against the page background, so it
   fails as link text. Same hue lightened to #5C8DFF reaches 6.22:1 on the
   page and handles text. Fills use the brand blue exactly; text uses the
   lightened version.
   ========================================================================== */

:root {
  /* Tells the browser to render scrollbars, date pickers, and other native
     controls in their dark variants. */
  color-scheme: dark;

  /* Brand blues — all hue 222, sat 100%, sampled from BLC Logo 3.png */
  --blue:         #0046E6;  /* THE brand blue, straight off the logo.
                               Button and badge fills. White on it = 7.23:1 */
  --blue-hover:   #1F63FF;  /* one step lighter. White on it = 4.90:1 */
  --blue-bright:  #5C8DFF;  /* links, eyebrows, accents on dark = 6.22:1 */
  --blue-tint:    #0A1940;  /* blue-tinted panel behind card icons */
  --blue-deep:    #06143B;  /* CTA band background */

  /* The logo artwork uses pure #010102 for its splatter, which reads as a
     dull rectangle against the #0B0D10 page. This gradient pools true black
     behind the artwork and feathers it out, so the splatter has something to
     dissolve into instead of ending on a hard edge. Applied as a background
     on the img itself — it shows through the transparent pixels. */
  --logo-pool: radial-gradient(ellipse 54% 52% at 50% 50%,
                 #010102 0%,
                 #010102 44%,
                 rgba(1,1,2,0.80) 60%,
                 rgba(1,1,2,0.45) 74%,
                 rgba(1,1,2,0.15) 86%,
                 transparent 95%);

  /* Wider, softer version for the large home page logo, where a tight fade
     reads as a padded box rather than a glow. */
  --logo-pool-lg: radial-gradient(ellipse 62% 58% at 50% 50%,
                    #010102 0%,
                    #010102 30%,
                    rgba(1,1,2,0.92) 44%,
                    rgba(1,1,2,0.70) 56%,
                    rgba(1,1,2,0.44) 68%,
                    rgba(1,1,2,0.22) 79%,
                    rgba(1,1,2,0.08) 89%,
                    transparent 97%);

  /* Dark neutrals, darkest to lightest */
  --n-900:        #0B0D10;  /* page background */
  --n-850:        #101317;  /* alternating sections */
  --n-800:        #15181D;  /* cards, inputs */
  --n-750:        #1B1F25;  /* raised / hover */
  --n-700:        #242931;  /* borders */
  --n-600:        #333941;  /* stronger borders */
  --n-400:        #6E7885;  /* disabled, faint text */
  --n-300:        #98A2AE;  /* muted text */
  --n-100:        #C9D1DA;  /* secondary text */
  --n-000:        #EEF2F6;  /* primary text */
  --white:        #FFFFFF;

  /* Feedback */
  --danger:       #FF6B6B;
  --danger-bg:    #2A1416;

  /* Semantic */
  --bg:           var(--n-900);
  --bg-alt:       var(--n-850);
  --surface:      var(--n-800);
  --surface-2:    var(--n-750);
  --text:         var(--n-000);
  --text-soft:    var(--n-100);
  --text-muted:   var(--n-300);
  --border:       var(--n-700);
  --border-2:     var(--n-600);

  /* Type */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  /* Spacing scale */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;

  /* Other */
  --radius:    8px;
  --radius-lg: 14px;
  --shadow:    0 1px 3px rgba(0,0,0,0.5), 0 4px 12px rgba(0,0,0,0.35);
  --shadow-lg: 0 4px 14px rgba(0,0,0,0.55), 0 18px 44px rgba(0,0,0,0.45);
  --maxw:      1180px;
  --ease:      cubic-bezier(0.4, 0, 0.2, 1);
}

/* --------------------------------------------------------------- Reset -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--bg);
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 {
  margin: 0 0 var(--s-4);
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}

h1 { font-size: clamp(2rem, 5vw, 3.25rem); }
h2 { font-size: clamp(1.6rem, 3.5vw, 2.35rem); }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.05rem; }

p { margin: 0 0 var(--s-4); }

a { color: var(--blue-bright); text-decoration: none; }
a:hover { text-decoration: underline; }

ul, ol { margin: 0 0 var(--s-4); padding-left: var(--s-5); }
li { margin-bottom: var(--s-2); }

strong { color: var(--text); font-weight: 700; }

code {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1em 0.4em;
  font-size: 0.9em;
  color: var(--text-soft);
}

::selection { background: var(--blue); color: var(--white); }

/* Visible keyboard focus everywhere */
:focus-visible {
  outline: 3px solid var(--blue-bright);
  outline-offset: 2px;
  border-radius: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--blue);
  color: var(--white);
  padding: var(--s-3) var(--s-4);
  z-index: 200;
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------- Layout -- */

.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--s-5);
}

.section { padding: var(--s-8) 0; }
.section--tight { padding: var(--s-7) 0; }
.section--alt { background: var(--bg-alt); }

.section-head {
  max-width: 720px;
  margin: 0 auto var(--s-7);
  text-align: center;
}
.section-head p {
  font-size: 1.1rem;
  color: var(--text-muted);
  margin: 0;
}

/* An aside with some personality. Deliberately smaller and set apart from
   the line above so it reads as a wink rather than another sales claim. */
.quip {
  margin-top: var(--s-3) !important;
  font-size: 0.95rem;
  color: var(--blue-bright);
}


.eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-bright);
  margin-bottom: var(--s-3);
}

.grid { display: grid; gap: var(--s-5); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

.text-center { text-align: center; }
.muted { color: var(--text-muted); }

/* ------------------------------------------------------- Blue line rule -- */

.blue-line {
  height: 4px;
  width: 60px;
  background: var(--blue-bright);
  border: 0;
  margin: 0 0 var(--s-5);
}
.blue-line--center { margin-left: auto; margin-right: auto; }

/* ------------------------------------------------------------ Buttons -- */

.btn {
  display: inline-block;
  padding: var(--s-3) var(--s-6);
  font-size: 1rem;
  font-weight: 600;
  font-family: inherit;
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease),
              border-color 0.18s var(--ease), transform 0.12s var(--ease);
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: var(--blue);
  color: var(--white);
  border-color: var(--blue);
}
.btn--primary:hover { background: var(--blue-hover); border-color: var(--blue-hover); }

.btn--outline {
  background: transparent;
  color: var(--blue-bright);
  border-color: var(--blue);
}
.btn--outline:hover { background: var(--blue); color: var(--white); border-color: var(--blue); }

.btn--ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--border-2);
}
.btn--ghost:hover { border-color: var(--blue-bright); color: var(--blue-bright); }

.btn--lg { padding: var(--s-4) var(--s-7); font-size: 1.08rem; }
.btn--block { display: block; width: 100%; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}
.btn-row--center { justify-content: center; }

/* ------------------------------------------------------------- Header -- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(11,13,16,0.92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}
/* The thin blue line under the header — brand cue */
.site-header::after {
  content: "";
  display: block;
  height: 3px;
  background: var(--blue-bright);
}

/* Taller than a standard header because the logo is a stacked two-line
   wordmark rather than a horizontal one. At 72px the artwork could only be
   about 46px tall, which is not enough for a two-line mark to read. */
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: 88px;
}

.logo {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
  flex-shrink: 0;
}
.logo:hover { text-decoration: none; color: var(--blue-bright); }

/* The BLC mark. The full lockup is unreadable below about 90px tall, so the
   header uses a crop of just the letterforms and lets the text beside it
   carry the full company name. */
/* The logo IS the wordmark, so there is no text lockup beside it — that
   only repeated the company name back at itself. Sized by height, since
   the header's vertical space is the fixed dimension and the width of a
   stacked mark follows from it. box-sizing is border-box, so 70px here is
   62px of artwork plus 4px of fade above and below. */
.logo-mark {
  height: 70px;
  width: auto;
  flex-shrink: 0;
  padding: 4px 10px;
  background: var(--logo-pool);
}

/* Name and trade beside the mark. The parent link carries an aria-label,
   which overrides its contents for screen readers, so this does not get
   announced twice alongside the image alt text. */
.logo-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.logo-text small {
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 3px;
}


.nav { display: flex; align-items: center; gap: var(--s-2); }

.nav a {
  padding: var(--s-2) var(--s-4);
  font-size: 0.96rem;
  font-weight: 500;
  color: var(--text-soft);
  border-radius: var(--radius);
  text-decoration: none;
  /* "Team stores" is the only two-word link, so it is the only one that can
     break onto a second line when the bar gets tight. That made its row
     taller than the rest. Nothing in a nav should ever wrap. */
  white-space: nowrap;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.nav a:hover { color: var(--blue-bright); background: var(--blue-tint); text-decoration: none; }
.nav a.is-active { color: var(--blue-bright); font-weight: 600; }

.nav .btn { margin-left: var(--s-3); color: var(--white); }
.nav .btn:hover { background: var(--blue-hover); color: var(--white); }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  padding: var(--s-2) var(--s-3);
  cursor: pointer;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--text);
}

/* --------------------------------------------------------------- Hero -- */

.hero {
  padding: var(--s-9) 0;
  background:
    radial-gradient(ellipse 90% 70% at 12% 0%, rgba(0,70,230,0.22) 0%, transparent 62%),
    var(--bg);
  border-bottom: 1px solid var(--border);
}

.hero-inner {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: var(--s-8);
  align-items: center;
}

.hero h1 { margin-bottom: var(--s-5); }
.hero h1 .accent { color: var(--blue-bright); }

.hero-lede {
  font-size: 1.18rem;
  color: var(--text-soft);
  max-width: 54ch;
  margin-bottom: var(--s-6);
}

/* Grid rather than flex-wrap. Wrapping flex items break wherever the text
   happens to run out, which leaves ragged rows. A grid keeps the columns
   aligned, and with six items it divides evenly at one, two, or three
   columns, so no row is ever left short.

   The 200px minimum is deliberate. Three columns inside the hero text
   column leaves roughly 144px per label, which is narrow enough that five
   of the six bullets wrap onto a second line while the short one does not
   — that mismatch is what reads as ragged. At 200px the grid settles on
   two columns of about 256px, wide enough that every label fits on one
   line and all six sit level. */
.hero-points {
  list-style: none;
  padding: 0;
  margin: var(--s-6) 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-3) var(--s-5);
}
.hero-points li {
  margin: 0;
  padding-left: var(--s-5);
  position: relative;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--text-soft);
}
.hero-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 12px;
  height: 3px;
  background: var(--blue-bright);
}

/* Home page: the full logo lockup sits opposite the headline. No card or
   border around it — the artwork already has its own splatter edge, and a
   frame would fight with it. */
.hero-logo {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Generous padding so the black has somewhere to go. Because box-sizing is
   border-box, the artwork itself lands around 430px inside a 620px box. */
.hero-logo img {
  width: 100%;
  max-width: 620px;
  height: auto;
  padding: 15% 15%;
  background: var(--logo-pool-lg);
}

/* Retired: the About page placeholder box. Removed once the real Parma
   Police photo landed. Restore from git if another placeholder is ever
   needed.
.hero-visual {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.9rem;
  text-align: center;
  padding: var(--s-5);
  box-shadow: var(--shadow);
}
*/

/* ---------------------------------------------------------- Our story -- */
/* Long-form prose. Capped near 70 characters per line, which is where
   reading comfort sits, and centred so it does not run the full container
   width like the card grids do. */

.story {
  max-width: 760px;
  margin: 0 auto;
}
.story p { color: var(--text-soft); }
.story h3 {
  margin-top: var(--s-7);
  margin-bottom: var(--s-4);
  color: var(--blue-bright);
  font-size: 1.3rem;
}
/* The story now opens on a subhead, so the first one loses the top margin
   that separates the later ones — the section padding already provides it. */
.story > h3:first-child { margin-top: 0; }
/* Photos inside the story. Capped at the image's own pixel width so it is
   never upscaled — an enlarged photo looks softer than a smaller sharp one.
   Centred, since it is narrower than the text column. */
.story-figure {
  margin: var(--s-7) auto;
  max-width: 640px;
}
.story-figure img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  display: block;
}
.story-figure figcaption {
  margin-top: var(--s-3);
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--text-muted);
  text-align: center;
}

/* The last line of the story. Given weight because it is the line the
   whole page has been building toward. */
.story-close {
  margin-top: var(--s-6);
  padding-left: var(--s-5);
  border-left: 3px solid var(--blue-bright);
  border-radius: 0;
  font-size: 1.18rem;
  line-height: 1.55;
  color: var(--text) !important;
}

/* Signs the story off. A named person at the end of a first-person page
   does more for trust than another paragraph would. */
.story-signature {
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--border);
  font-size: 0.95rem;
  color: var(--text-muted) !important;
  line-height: 1.5;
}
.story-signature-name {
  display: block;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
}

/* --------------------------------------------------- Page header (sub) -- */

.page-head {
  padding: var(--s-8) 0 var(--s-7);
  background: var(--bg-alt);
  border-bottom: 1px solid var(--border);
}
.page-head h1 { margin-bottom: var(--s-4); }
.page-head p {
  font-size: 1.12rem;
  color: var(--text-soft);
  max-width: 62ch;
  margin: 0;
}

/* A closing statement inside the page header rather than the body. Sits
   below the intro with a blue rule, so it reads as the point being made
   rather than the first line of the article underneath. */
.page-head-line {
  margin-top: var(--s-5) !important;
  padding-left: var(--s-5);
  border-left: 3px solid var(--blue-bright);
  font-size: 1.22rem !important;
  line-height: 1.5;
  font-weight: 600;
  color: var(--text) !important;
}

/* -------------------------------------------------------------- Cards -- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease),
              border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-2);
  background: var(--surface-2);
}
.card h3 { margin-bottom: var(--s-3); }
.card p { color: var(--text-soft); }
.card p:last-child { margin-bottom: 0; }

.card-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--radius);
  background: var(--blue-tint);
  color: var(--blue-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: var(--s-4);
}

/* ------------------------------------------------- Announcement bar -- */
/* Sits above the hero so it is the first thing read, but kept to a single
   line. A full announcement block here would push the headline and the
   quote buttons about 500px down the page, which means a first-time
   visitor reads about features they cannot use yet before learning what
   the business actually does.

   The whole bar is one link down to the detail further down the page, so
   the cost up top stays at roughly 50px. */

.announce {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-3);
  padding: var(--s-3) var(--s-5);
  background: var(--blue-deep);
  border-bottom: 1px solid var(--border);
  color: var(--text-soft);
  font-size: 0.92rem;
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  transition: background 0.18s var(--ease);
}
.announce:hover { background: var(--blue-tint); text-decoration: none; }
.announce:hover .announce-more { color: var(--white); }

.announce-tag {
  flex-shrink: 0;
  padding: 2px var(--s-3);
  border-radius: 999px;
  background: var(--blue);
  color: var(--white);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.announce-more {
  flex-shrink: 0;
  font-weight: 600;
  color: var(--blue-bright);
  transition: color 0.18s var(--ease);
}

/* On a phone the full sentence plus the prompt runs to four or five lines,
   which is no longer a bar. The sentence carries the message on its own. */
@media (max-width: 620px) {
  .announce { font-size: 0.86rem; padding: var(--s-3) var(--s-4); }
  .announce-more { display: none; }
}

/* Marks a feature that is announced but not built yet. Deliberately a quiet
   outline rather than a solid blue fill: a badge that shouts competes with
   the heading beneath it, and this has to read as an honest label rather
   than a promotion. Sitting above the heading means it is read first, so
   nobody gets halfway through a description before learning they cannot
   use the thing yet. */
.soon {
  display: inline-block;
  margin-bottom: var(--s-3);
  padding: 3px var(--s-3);
  border: 1px solid var(--blue);
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--blue-bright);
  background: var(--blue-tint);
}

.card--flat { background: var(--bg-alt); border: 1px solid var(--border); }
.card--flat:hover { transform: none; box-shadow: none; background: var(--surface); }

/* Photo behind a service card, set per card with --card-img.

   Two stacked layers rather than one. ::before holds the photo at low
   opacity; ::after lays a dark gradient over it. The gradient is what keeps
   the text readable — opacity alone is not enough, because a bright patch
   in a photo (a white jersey, sky) stays bright at any opacity and text
   crossing it loses contrast even when the average looks fine.

   The two numbers have to be read together, which is the mistake made here
   first time around: the photo was set to 18% and then covered by a gradient
   running 55% to 94%. Those multiply. What actually survived to the screen
   was 18% x 45% = 8% of the photo at the top of the card and 1% at the
   bottom, which is indistinguishable from no photo at all.

   So the photo layer is now high — 85% — and the gradient above it does all
   the real work of protecting the text. Effective photo strength lands
   around 24% at the top and 10% at the bottom. */
.card--photo {
  position: relative;
  overflow: hidden;

  /* The twelve card photos come to about 1.3MB, and every one of them was
     being fetched on page load — including the eight or nine below the fold
     that most visitors never scroll to. A background image cannot carry
     loading="lazy", so the usual fix does not apply.

     content-visibility: auto tells the browser it may skip all rendering
     work for this element while it is off screen, and skipped subtrees do
     not fetch their background images until they are approached. The images
     still arrive, just as the reader reaches them.

     contain-intrinsic-size is what makes this safe. Without it a skipped
     card reports zero height, the page collapses, and the scrollbar jumps
     as cards render. The value is a placeholder height held until the card
     has been laid out once; the auto keyword then remembers the real height
     and reuses it, so the guess only ever matters on first paint.

     Unsupported browsers ignore both lines and load exactly as before. */
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}
.card--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0.85;
  transition: opacity 0.25s var(--ease), transform 0.4s var(--ease);
}

/* Paths live here rather than in a --card-img custom property on the HTML.
   url() inside a custom property does not resolve reliably — some browsers
   resolve it against the stylesheet rather than the document, which turns
   assets/img/... into assets/css/assets/img/... and silently loads nothing.
   Declared here, the paths are relative to this file and unambiguous. */
.card--apparel::before   { background-image: url('../img/gallery/apparel-champ-hoodies.webp'); }
.card--embroidery::before{ background-image: url('../img/gallery/cap-snake.webp'); }
.card--uniforms::before  { background-image: url('../img/gallery/uniforms-venom.webp'); }
.card--promo::before     { background-image: url('../img/gallery/promo-challenge-coin.webp'); }
.card--print::before     { background-image: url('../img/gallery/print-business-cards.webp'); }
/* Sponsor banner at a golf outing. Better here than the vehicle wrap: it is
   unmistakably large format, it is outdoors in weather, and Blue Line Crafts
   is one of the logos on it — the shop's own name on its own work. The
   vehicle photo stays in the gallery. */
.card--signage::before   { background-image: url('../img/gallery/signage-banner-golf.webp'); }
.card--labels::before    { background-image: url('../img/gallery/print-roll-labels.webp?v=2'); }

/* The team stores source has a navy "TEAM STORES" banner across the top,
   which would sit directly behind the card's own heading and make both
   unreadable. Cropped out here with background-position rather than by
   editing the file: pushing the frame down past 100% keeps only the lower
   part of the image, which is the device mockup. */
/* Bob recropped the source with the TEAM STORES banner removed, so the CSS
   crop that was here is gone. Cropping in the browser was always the weaker
   option — it scaled the image up to push the banner out of frame, costing
   sharpness and cutting the sides, and it had to be retuned for every card
   shape. A correctly cropped file needs none of that.

   Different filename, so it also sidesteps the poisoned cache entries
   entirely rather than relying on a version string. */
.card--stores::before    { background-image: url('../img/gallery/stores-team-stores-cropped.webp'); }

/* Home page. These three carried numbered blue squares, left over from when
   the services page did. The numbers implied an order that does not exist —
   they are three offerings, not three steps, and the How it works section
   directly below is the part that is actually sequential. Removed. */
.card--home-uniforms::before { background-image: url('../img/gallery/uniforms-jersey-sample.webp?v=2'); }
.card--home-spirit::before   { background-image: url('../img/gallery/spiritwear-cardinals.webp'); }
.card--home-stores::before   { background-image: url('../img/gallery/stores-team-stores-cropped.webp'); }

/* Uniform accessories */
.card--hats::before      { background-image: url('../img/gallery/cap-chief.webp'); }
.card--socks::before     { background-image: url('../img/gallery/acc-socks.webp'); }
.card--belts::before     { background-image: url('../img/gallery/acc-belt.webp'); }
.card--bags::before      { background-image: url('../img/gallery/acc-bat-bag.webp?v=2'); }
/* Lightest at the top, where the heading is — a bright heading can take it.
   Darkens toward the bottom, where the small muted list text lives.

   Checked against the worst case rather than the average: a pure white pixel
   in a photo. Even there the darkest text on the card clears 5.5:1, so no
   photo can push any card below AA no matter what gets swapped in later. */
.card--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg,
              rgba(21,24,29,0.72) 0%,
              rgba(21,24,29,0.80) 45%,
              rgba(21,24,29,0.88) 100%);
}
/* Everything in the card has to sit above both layers */
.card--photo > * { position: relative; z-index: 1; }

/* The bullet lists use --text-muted elsewhere, which is deliberately faint.
   Over a photo that faintness is what fails contrast first and it is the
   single thing capping how visible the photo is allowed to be. One step
   brighter costs nothing on a plain card and buys the photo real presence. */
.card--photo ul li { color: var(--text-soft); }

.card--photo:hover::before {
  opacity: 1;
  transform: scale(1.04);
}

.card ul { margin: var(--s-4) 0 0; padding-left: var(--s-5); }
.card ul li { font-size: 0.94rem; color: var(--text-muted); }

/* --------------------------------------------------------- Steps (1-2-3) -- */

.steps { counter-reset: step; }
.step { position: relative; padding-left: var(--s-8); }
.step::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--blue);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.05rem;
}
.step h3 { margin-bottom: var(--s-2); font-size: 1.12rem; }
.step p { margin: 0; color: var(--text-muted); font-size: 0.96rem; }

/* ------------------------------------------------------------ Gallery -- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  justify-content: center;
  margin-bottom: var(--s-7);
}
.filter-btn {
  padding: var(--s-2) var(--s-5);
  font-size: 0.92rem;
  font-family: inherit;
  font-weight: 500;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: all 0.15s var(--ease);
}
.filter-btn:hover { border-color: var(--blue-bright); color: var(--blue-bright); }
.filter-btn.is-active {
  background: var(--blue);
  border-color: var(--blue);
  color: var(--white);
}

.gallery-item {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface);
}
.gallery-item[hidden] { display: none; }

/* Masonry, via CSS columns.

   The work here is mixed orientation — badges and tumblers are tall, caps
   and banners are wide. Any single fixed tile ratio crops one group or the
   other badly: a square cut the eagle off the badge, and 4:5 would slice
   the peak off every cap. Letting each tile keep its own proportions means
   nothing is ever cropped, and an uneven grid reads as a portfolio rather
   than a spreadsheet.

   columns rather than grid because CSS grid still has no real masonry in
   shipping browsers. The tradeoff is that columns order top-to-bottom
   within each column instead of left-to-right, which does not matter for
   a gallery with no reading order. */
.gallery-masonry {
  columns: 3;
  column-gap: var(--s-5);
}
.gallery-masonry .gallery-item {
  break-inside: avoid;
  margin: 0 0 var(--s-5);
  display: inline-block;
  width: 100%;
}

.gallery-thumb {
  background: var(--n-850);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.85rem;
  text-align: center;
  overflow: hidden;
}
/* Placeholders have no image to set their height, so they need a ratio */
.gallery-thumb--empty {
  aspect-ratio: 4 / 5;
  padding: var(--s-4);
}

.gallery-thumb img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 0.4s var(--ease);
}
.gallery-item:hover .gallery-thumb img { transform: scale(1.03); }

@media (max-width: 900px) { .gallery-masonry { columns: 2; } }
@media (max-width: 620px) { .gallery-masonry { columns: 1; } }

.gallery-meta { padding: var(--s-4) var(--s-5); }
.gallery-meta h4 { margin: 0 0 var(--s-1); font-size: 1rem; }
.gallery-meta span { font-size: 0.85rem; color: var(--text-muted); }

/* --------------------------------------------------------------- Forms -- */

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-5);
}

.field { display: flex; flex-direction: column; }
.field--full { grid-column: 1 / -1; }

.field label {
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: var(--s-2);
  color: var(--text-soft);
}
.field .req { color: var(--danger); }
.field .hint {
  font-size: 0.82rem;
  color: var(--text-muted);
  font-weight: 400;
  margin-top: var(--s-1);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  font-size: 1rem;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease),
              background 0.15s var(--ease);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--n-400); }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  background: var(--surface-2);
  border-color: var(--blue-bright);
  box-shadow: 0 0 0 3px rgba(92,141,255,0.25);
}
.field textarea { resize: vertical; min-height: 130px; }

/* Date and file inputs render their own controls — force them light-on-dark */
.field input[type="date"] { color-scheme: dark; }
.field input[type="file"] {
  padding: var(--s-3);
  color: var(--text-muted);
  font-size: 0.92rem;
}
.field input[type="file"]::file-selector-button {
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  padding: var(--s-2) var(--s-4);
  margin-right: var(--s-4);
  cursor: pointer;
}
.field input[type="file"]::file-selector-button:hover {
  border-color: var(--blue-bright);
  color: var(--blue-bright);
}

.field-error {
  font-size: 0.85rem;
  color: var(--danger);
  margin-top: var(--s-2);
  display: none;
}
.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--danger); }
.field.has-error .field-error { display: block; }

.form-note {
  font-size: 0.88rem;
  color: var(--text-muted);
  margin-top: var(--s-4);
}

/* Terms shown at the point of submission rather than linked away to a
   separate page. A notice someone had to click through to is far weaker
   than one sitting directly above the thing they are agreeing to. */
.terms-note {
  background: var(--n-850);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-4);
}
.terms-note h4 {
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--s-3);
}
.terms-note p {
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--text-soft);
  margin-bottom: var(--s-3);
}
.terms-note p:last-child { margin-bottom: 0; }

/* Checkbox row. The whole label is clickable, and the box does not shrink
   when the text beside it wraps to a second line. */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  cursor: pointer;
  font-size: 0.94rem;
  font-weight: 500;
  color: var(--text-soft);
  line-height: 1.5;
}
.check input[type="checkbox"] {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin: 2px 0 0;
  accent-color: var(--blue);
  cursor: pointer;
}
.field.has-error .check { color: var(--danger); }
.field.has-error .check input[type="checkbox"] { outline: 2px solid var(--danger); outline-offset: 2px; }

.form-status {
  padding: var(--s-4) var(--s-5);
  border-radius: var(--radius);
  margin-bottom: var(--s-5);
  font-weight: 500;
  display: none;
  border: 1px solid transparent;
}
.form-status.is-visible { display: block; }
.form-status--ok {
  background: var(--blue-tint);
  border-color: var(--blue);
  color: var(--blue-bright);
}
.form-status--err {
  background: var(--danger-bg);
  border-color: var(--danger);
  color: var(--danger);
}

/* ------------------------------------------------------- Contact info -- */

.info-list { list-style: none; padding: 0; margin: 0; }
.info-list li {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--border);
  margin: 0;
}
.info-list li:last-child { border-bottom: 0; }
.info-list dt,
.info-list .label {
  font-weight: 600;
  font-size: 0.88rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  min-width: 90px;
  flex-shrink: 0;
}

.hours-table { width: 100%; border-collapse: collapse; font-size: 0.96rem; }
.hours-table th,
.hours-table td {
  text-align: left;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border);
}
.hours-table th { font-weight: 600; color: var(--text-soft); }
.hours-table td { color: var(--text-muted); text-align: right; }
.hours-table tr:last-child th,
.hours-table tr:last-child td { border-bottom: 0; }

/* ----------------------------------------------------------- FAQ / details -- */

.faq details {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-3);
  background: var(--surface);
  transition: border-color 0.15s var(--ease);
}
.faq details:hover { border-color: var(--border-2); }
.faq details[open] { border-color: var(--border-2); background: var(--surface-2); }
.faq summary {
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  position: relative;
  padding-right: var(--s-6);
  color: var(--text);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: -2px;
  font-size: 1.35rem;
  font-weight: 400;
  color: var(--blue-bright);
  line-height: 1;
}
.faq details[open] summary::after { content: "\2013"; }
.faq details p { margin: var(--s-4) 0 0; color: var(--text-soft); }
.faq details p:last-child { margin-bottom: 0; }

/* ----------------------------------------------------------- CTA band -- */

.cta-band {
  background: var(--blue-deep);
  color: var(--text);
  padding: var(--s-8) 0;
  text-align: center;
  position: relative;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.cta-band::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: var(--blue-bright);
}
.cta-band h2 { color: var(--white); }
.cta-band p {
  color: var(--n-100);
  font-size: 1.1rem;
  max-width: 56ch;
  margin: 0 auto var(--s-6);
}
.cta-band .btn--ghost {
  background: transparent;
  color: var(--white);
  border-color: rgba(255,255,255,0.38);
}
.cta-band .btn--ghost:hover {
  background: var(--white);
  color: var(--blue-deep);
  border-color: var(--white);
}

/* ------------------------------------------------------------- Footer -- */

.site-footer {
  background: var(--n-850);
  border-top: 1px solid var(--border);
  padding: var(--s-7) 0 var(--s-5);
  font-size: 0.94rem;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: var(--s-7);
  margin-bottom: var(--s-6);
}

.footer-logo {
  display: inline-block;
  margin-bottom: var(--s-4);
  opacity: 0.9;
  transition: opacity 0.18s var(--ease);
}
.footer-logo:hover { opacity: 1; }
.footer-logo img {
  width: 100%;
  max-width: 280px;
  height: auto;
  padding: 5% 4%;
  background: var(--logo-pool);
}

.site-footer h4 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: var(--s-4);
}
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: var(--s-2); }
.site-footer a { color: var(--text-soft); }
.site-footer a:hover { color: var(--blue-bright); }
.site-footer p { color: var(--text-muted); margin-bottom: var(--s-3); }

.footer-bottom {
  border-top: 1px solid var(--border);
  padding-top: var(--s-5);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s-3);
  color: var(--text-muted);
  font-size: 0.88rem;
}

/* ---------------------------------------------------------------- 404 -- */

.error-page {
  min-height: 55vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--s-9) var(--s-5);
}
.error-code {
  font-size: 5rem;
  font-weight: 800;
  color: var(--blue-bright);
  line-height: 1;
  margin-bottom: var(--s-4);
}

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

@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; gap: var(--s-6); }
  .hero { padding: var(--s-8) 0; }
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--s-6); }
}

/* The horizontal bar needs roughly 790px of viewport before the links
   start being squeezed. Collapsing at 768px left a band where the nav
   was cramped but still horizontal. Switching at 860px gives headroom. */
@media (max-width: 860px) {
  .nav-toggle { display: block; }

  .site-header { position: relative; }

  .nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-1);
    background: var(--n-850);
    border-bottom: 1px solid var(--border);
    padding: var(--s-3);
    box-shadow: var(--shadow-lg);
  }

  .nav.is-open { display: flex; }

  /* Every row gets identical padding and alignment. Previously the links
     sat flush with gap 0 while the CTA carried its own top margin, and the
     CTA was centred while the links were left aligned, so no two rows lined
     up the same way. */
  .nav a {
    padding: var(--s-3) var(--s-4);
    font-size: 1rem;
    border-radius: var(--radius);
    text-align: left;
  }

  /* The CTA sits below a divider so it reads as separate from the list
     rather than as a misaligned member of it. Its 2px button border would
     otherwise make it taller than every link, so the vertical padding drops
     by that much to match. */
  .nav .btn {
    margin: var(--s-3) 0 0;
    padding: calc(var(--s-3) - 2px) var(--s-4);
    line-height: 1.65;
    text-align: center;
    border-radius: var(--radius);
  }

  .nav a.btn { position: relative; }

  .nav a.btn::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(var(--s-3) / -2 - 1px);
    height: 1px;
    background: var(--border);
  }
}

@media (max-width: 768px) {
  body { font-size: 16px; }

  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; }

  .section { padding: var(--s-7) 0; }
  .hero-points { grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
  .btn-row .btn { width: 100%; }
}

@media (max-width: 560px) {
  /* Below this width the mark plus the text lockup crowds the menu button.
     The mark carries the brand on its own, so the text steps aside. */
  .logo-mark { height: 62px; }
}

/* Below this, two columns leaves under 190px per label and most of them
   wrap. One full-width column is cleaner than two cramped ones. */
@media (max-width: 580px) {
  .hero-points { grid-template-columns: 1fr; gap: var(--s-2); }
}

/* The lockup needs about 316px alongside the hamburger. Everything down to
   a 360px phone clears that; below it the text has to go so the mark and
   the menu button are not squeezed. */
@media (max-width: 350px) {
  .logo-text { display: none; }
}

@media (max-width: 420px) {
  .container { padding: 0 var(--s-4); }
  .logo-mark { height: 56px; }
}

/* -------------------------------------------------------------- Print -- */
/* Force light for print — nobody wants a black page coming out of a printer */

@media print {
  html, body { background: #FFF; color: #000; }
  .site-header, .site-footer, .cta-band, .nav-toggle, .btn { display: none; }
  body { font-size: 12pt; }
  h1, h2, h3, h4, p, li, td, th, summary { color: #000 !important; }
  .card, .faq details { background: #FFF; border: 1px solid #CCC; }
  a { color: #000; text-decoration: underline; }
}

/* ------------------------------------------------- Reduced motion -- */

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