/* ===========================================================================
   NOIR CHROMA — Global chrome
   ---------------------------------------------------------------------------
   Desktop-first. Everything ≤900px lives in css/mobile.css.

   Every selector is prefixed with body[data-skin="noir"]. That is not just
   scoping hygiene: assets/css/footer-redesign.css is linked from
   inc/footer.php, i.e. AFTER this file in document order, and it hardens its
   own colours with .sfd .sfd-h (0-2-0) style selectors. The prefix lifts us
   to 0-2-1+ so specificity alone wins — no !important needed.

   Outside css/search-page.css the skin uses exactly three !important
   declarations, and every one of them cancels an existing !important or an
   inline style:
     1. body background under 600px   — counters style.css:686
     2. .search-hero-banner on phones — counters index-page.css:707, which
        hides the hero for a mobile layer this skin no longer loads
     3. .info-panel on contact.php    — counters an inline style written by PHP
   css/search-page.css is the documented exception: assets/css/search-page.css
   was deliberately written to resist skins and forces ~35 colours with
   !important, so that file has to answer in kind. Its header explains why.
   =========================================================================== */

/* ---- 1. Base ------------------------------------------------------------ */

body[data-skin="noir"] {
  background: var(--n-bg);
  color: var(--n-text);
  font-family: var(--n-font-body);
  font-size: var(--n-fz-base);
  line-height: var(--n-lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body[data-skin="noir"] ::selection {
  background: rgba(255, 61, 139, .30);
  color: var(--n-fg);
}

body[data-skin="noir"] .container {
  max-width: var(--n-maxw);
  padding-inline: max(var(--n-gutter), var(--n-safe-left), var(--n-safe-right));
}

body[data-skin="noir"] h1,
body[data-skin="noir"] h2,
body[data-skin="noir"] h3,
body[data-skin="noir"] h4 {
  font-family: var(--n-font-display);
  color: var(--n-text);
  line-height: var(--n-lh-tight);
  letter-spacing: -.015em;
}

body[data-skin="noir"] p { color: var(--n-text); }
body[data-skin="noir"] a { color: var(--n-text); }

body[data-skin="noir"] hr {
  border: 0;
  height: 1px;
  background: var(--n-border);
}

body[data-skin="noir"] img { background-color: transparent; }

/* Firefox scrollbar; WebKit below. */
body[data-skin="noir"] { scrollbar-color: var(--n-ink-5) var(--n-ink-0); }
body[data-skin="noir"] ::-webkit-scrollbar { width: 10px; height: 10px; }
body[data-skin="noir"] ::-webkit-scrollbar-track { background: var(--n-ink-0); }
body[data-skin="noir"] ::-webkit-scrollbar-thumb {
  background: var(--n-ink-5);
  border-radius: var(--n-r-pill);
  border: 2px solid var(--n-ink-0);
}
body[data-skin="noir"] ::-webkit-scrollbar-thumb:hover { background: #33333B; }


/* ---- 2. Gradient text utility ------------------------------------------ */
/* Declared as a named class so every page file uses the same guarded recipe:
   a solid colour first, then the clip trio only where it is supported. If
   background-clip:text is missing — or the a11y widget's invert filter is on —
   the text is still there and still readable. */

body[data-skin="noir"] .n-grad-text {
  color: var(--n-fg);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  body[data-skin="noir"] .n-grad-text {
    background: var(--n-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}


/* ---- 3. Header ---------------------------------------------------------- */

body[data-skin="noir"] .header-wrap {
  height: var(--n-header-h);
  background: rgba(11, 11, 13, .72);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-bottom: 1px solid var(--n-border);
  box-shadow: none;
  padding-top: var(--n-safe-top);
  transition: background var(--n-dur) var(--n-ease);
}

/* Low Power Mode and older engines drop backdrop-filter — never let the
   header become a transparent smear over the gallery. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body[data-skin="noir"] .header-wrap { background: var(--n-ink-1); }
}

/* The chromatic hairline. Sits on the header's bottom edge. */
body[data-skin="noir"] .header-wrap::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 1px;
  background: var(--n-grad-line);
  opacity: .55;
  pointer-events: none;
}

body[data-skin="noir"] .header {
  max-width: var(--n-maxw);
  padding-inline: max(var(--n-gutter), var(--n-safe-left), var(--n-safe-right));
}

body[data-skin="noir"] .brand-logo-img {
  height: 34px;
  max-width: 172px;
  transition: opacity var(--n-dur) var(--n-ease);
}
body[data-skin="noir"] .brand a:hover .brand-logo-img { opacity: .82; }

body[data-skin="noir"] .brand h1,
body[data-skin="noir"] .brand a > span:not(.brand-dot) {
  font-family: var(--n-font-display);
  color: var(--n-fg);
}
body[data-skin="noir"] .brand-dot {
  background: var(--n-grad);
  border-radius: 2px;
}


/* ---- 4. Navigation (desktop) -------------------------------------------- */

body[data-skin="noir"] .nav { gap: var(--n-s5); }

body[data-skin="noir"] .nav-link {
  position: relative;
  color: var(--n-text-muted);
  font-family: var(--n-font-display);
  font-size: var(--n-fz-sm);
  font-weight: var(--n-fw-med);
  letter-spacing: var(--n-tracking-wide);
  border-bottom: 0;
  transition: color var(--n-dur) var(--n-ease);
}

/* The gradient underline lives on a pseudo-element so the base rule's
   border-bottom-color (which cannot hold a gradient) is simply retired. */
body[data-skin="noir"] .nav-link::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--n-grad);
  transform: scaleX(0);
  transform-origin: center;
  opacity: 0;
  transition: transform var(--n-dur) var(--n-ease-emph), opacity var(--n-dur) var(--n-ease);
}

body[data-skin="noir"] .nav-link:hover { color: var(--n-fg); }
body[data-skin="noir"] .nav-link:hover::after { transform: scaleX(.45); opacity: .6; }

body[data-skin="noir"] .nav-link.active { color: var(--n-fg); }
body[data-skin="noir"] .nav-link.active::after { transform: scaleX(1); opacity: 1; }

body[data-skin="noir"] .nav-link--admin { color: var(--n-accent); }
body[data-skin="noir"] .nav-link--lang {
  font-weight: var(--n-fw-bold);
  padding-inline: var(--n-s3);
  border: 1px solid var(--n-border-strong);
  border-radius: var(--n-r-pill);
  height: 32px;
  align-self: center;
}
body[data-skin="noir"] .nav-link--lang::after { display: none; }
body[data-skin="noir"] .nav-link--lang:hover { border-color: var(--n-accent); }

body[data-skin="noir"] .icon-bar {
  background: var(--n-fg);
  border-radius: 2px;
}


/* ---- 5. Buttons --------------------------------------------------------- */

body[data-skin="noir"] .btn {
  background: var(--n-grad);
  color: var(--n-on-accent);
  -webkit-text-fill-color: var(--n-on-accent);
  border: 0;
  border-radius: var(--n-r-pill);
  padding: .8rem 1.75rem;
  font-family: var(--n-font-display);
  font-weight: var(--n-fw-bold);
  letter-spacing: var(--n-tracking-wide);
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--n-dur) var(--n-ease),
              box-shadow var(--n-dur) var(--n-ease),
              filter var(--n-dur) var(--n-ease);
}
body[data-skin="noir"] .btn:hover {
  opacity: 1;
  transform: translateY(-2px);
  filter: brightness(1.08);
  box-shadow: var(--n-glow);
}
body[data-skin="noir"] .btn:active { transform: translateY(0); }

body[data-skin="noir"] .btn.light {
  background: transparent;
  color: var(--n-fg);
  -webkit-text-fill-color: var(--n-fg);
  border: 1px solid var(--n-border-strong);
}
body[data-skin="noir"] .btn.light:hover {
  background: var(--n-surface-2);
  border-color: var(--n-accent);
  filter: none;
  box-shadow: none;
}

body[data-skin="noir"] .btn.danger {
  background: transparent;
  color: var(--n-danger);
  -webkit-text-fill-color: var(--n-danger);
  border: 1px solid rgba(255, 92, 108, .35);
}
body[data-skin="noir"] .btn.danger:hover {
  background: rgba(255, 92, 108, .10);
  filter: none;
  box-shadow: none;
}

body[data-skin="noir"] .btn.sm { padding: .45rem 1.1rem; font-size: var(--n-fz-xs); }


/* ---- 6. Surfaces: cards, chips, pills ----------------------------------- */

body[data-skin="noir"] .card {
  background: var(--n-surface);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-lg);
  box-shadow: none;
}

body[data-skin="noir"] .chip {
  background: var(--n-surface-2);
  color: var(--n-text-muted);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-pill);
  transition: color var(--n-dur) var(--n-ease),
              border-color var(--n-dur) var(--n-ease),
              background var(--n-dur) var(--n-ease);
}
body[data-skin="noir"] .chip:hover {
  color: var(--n-fg);
  border-color: var(--n-border-strong);
  background: var(--n-surface-hover);
}
body[data-skin="noir"] .chip.active {
  background: var(--n-grad);
  color: var(--n-on-accent);
  -webkit-text-fill-color: var(--n-on-accent);
  border-color: transparent;
}

body[data-skin="noir"] .tag-pill {
  background: var(--n-surface-2);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-pill);
  color: var(--n-text-muted);
  padding: .35rem .9rem;
}
body[data-skin="noir"] .tag-pill:hover {
  border-color: var(--n-accent);
  color: var(--n-fg);
}

body[data-skin="noir"] .copy-box {
  background: var(--n-surface-2);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-sm);
}
body[data-skin="noir"] .copy-msg {
  background: var(--n-success);
  color: var(--n-ink-0);
}
body[data-skin="noir"] .copy-icon { opacity: .6; }


/* ---- 7. Forms ----------------------------------------------------------- */

body[data-skin="noir"] .form-label {
  color: var(--n-text-muted);
  font-family: var(--n-font-display);
  letter-spacing: var(--n-tracking-wide);
}

body[data-skin="noir"] .form-input,
body[data-skin="noir"] .form-textarea,
body[data-skin="noir"] .modern-select,
body[data-skin="noir"] .search-main-input {
  background: var(--n-surface-2);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-sm);
  color: var(--n-text);
  -webkit-text-fill-color: var(--n-text);
  caret-color: var(--n-pink);
  /* 16px minimum: anything smaller makes iOS Safari zoom the viewport on
     focus, which the user cannot zoom back out of on some pages. */
  font-size: max(16px, var(--n-fz-base));
  transition: border-color var(--n-dur) var(--n-ease), box-shadow var(--n-dur) var(--n-ease);
}

body[data-skin="noir"] .form-input::placeholder,
body[data-skin="noir"] .form-textarea::placeholder,
body[data-skin="noir"] input::placeholder,
body[data-skin="noir"] textarea::placeholder {
  color: var(--n-text-dim);
  -webkit-text-fill-color: var(--n-text-dim);
  opacity: 1;
}

body[data-skin="noir"] .form-input:focus,
body[data-skin="noir"] .form-textarea:focus {
  outline: none;
  border-color: var(--n-accent);
  box-shadow: 0 0 0 3px rgba(255, 61, 139, .18);
}

/* WebKit repaints autofilled fields with its own opaque background. The
   1000px inset shadow is the only reliable way to hold our own colour, and
   the absurd transition delay stops the yellow flash on first paint. */
body[data-skin="noir"] input:-webkit-autofill,
body[data-skin="noir"] input:-webkit-autofill:hover,
body[data-skin="noir"] input:-webkit-autofill:focus,
body[data-skin="noir"] textarea:-webkit-autofill,
body[data-skin="noir"] select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--n-surface-2) inset;
  -webkit-text-fill-color: var(--n-text);
  caret-color: var(--n-pink);
  transition: background-color 9999s ease-in-out 0s;
}

/* Native selects that are NOT replaced by custom-dropdown.js. The chevron is
   a data URI, which is safe here because this is an external stylesheet —
   inside an inline <style> the '<svg' token breaks the iOS Safari HTML
   parser and kills every rule after it. */
body[data-skin="noir"] select {
  color-scheme: dark;
  background-color: var(--n-surface-2);
  color: var(--n-text);
  -webkit-text-fill-color: var(--n-text);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-sm);
  font-size: max(16px, var(--n-fz-sm));
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23A09B95' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left .75rem center;
  background-size: 16px 16px;
  padding-inline-end: 1rem;
  padding-inline-start: 2.25rem;
}
html[dir="ltr"] body[data-skin="noir"] select {
  background-position: right .75rem center;
  padding-inline-end: 2.25rem;
  padding-inline-start: 1rem;
}
body[data-skin="noir"] select option {
  background-color: var(--n-ink-3);
  color: var(--n-text);
}

body[data-skin="noir"] .search-wrapper {
  background: var(--n-surface);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-lg);
  box-shadow: none;
}
body[data-skin="noir"] .search-btn-hero {
  background: var(--n-grad);
  color: var(--n-on-accent);
  border-radius: var(--n-r-pill);
}


/* ---- 8. Section titles -------------------------------------------------- */

body[data-skin="noir"] .modern-section-title { margin: var(--n-s8) 0 var(--n-s6); }

body[data-skin="noir"] .modern-section-title h2 {
  font-family: var(--n-font-display);
  font-size: var(--n-fz-3xl);
  font-weight: var(--n-fw-bold);
  letter-spacing: -.02em;
  filter: none;
  color: var(--n-fg);
  background: none;
  -webkit-text-fill-color: currentColor;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  body[data-skin="noir"] .modern-section-title h2 {
    background: var(--n-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}


/* ---- 9. Gallery primitives (base level) --------------------------------- */
/* index-page.css refines these; declared here so every page that reuses the
   grid — search results, tag pages — inherits the same treatment. */

body[data-skin="noir"] .gallery-grid { gap: 2px; }

body[data-skin="noir"] .gallery-tile {
  background: var(--n-ink-2);
  border-radius: var(--n-r-xs);
}
body[data-skin="noir"] .gallery-tile:hover { box-shadow: none; }

body[data-skin="noir"] .gallery-tile img {
  transition: transform var(--n-dur-slow) var(--n-ease-emph),
              filter var(--n-dur-slow) var(--n-ease);
  filter: brightness(.92);
}
body[data-skin="noir"] .gallery-tile:hover img {
  transform: scale(1.04);
  filter: brightness(1.05);
}

/* The legacy hover caption is superseded by .tile-meta (see index-page.css)
   and is never emitted by the new partial, but old cached markup might still
   carry it — keep it dark rather than a white slab. */
body[data-skin="noir"] .tile-overlay {
  background: linear-gradient(to top, rgba(11, 11, 13, .92), rgba(11, 11, 13, 0));
  border-top: 0;
}
body[data-skin="noir"] .tile-title { color: var(--n-fg); }

/* .feed-tile holds admin-authored HTML of unknown shape. Contain it
   structurally instead of nuking its text, which is what the legacy inline
   block did with font-size:0 + display:none on every child. */
body[data-skin="noir"] .feed-tile {
  aspect-ratio: 2 / 3;
  overflow: hidden;
  contain: content;
  isolation: isolate;
  background: var(--n-ink-2);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-xs);
  color: var(--n-text);
  box-shadow: none;
}
body[data-skin="noir"] .feed-tile:hover {
  transform: none;
  border-color: var(--n-border-strong);
  box-shadow: none;
}
body[data-skin="noir"] .feed-text-content {
  background: var(--n-ink-3);
  color: var(--n-text);
  font-family: var(--n-font-display);
}
body[data-skin="noir"] .feed-overlay-text {
  background: linear-gradient(to top, rgba(11, 11, 13, .92), rgba(11, 11, 13, 0));
  color: var(--n-fg);
  text-shadow: none;
  font-size: var(--n-fz-sm);
  line-height: var(--n-lh-snug);
}


/* ---- 10. Loader --------------------------------------------------------- */

body[data-skin="noir"] .spinner {
  border-color: var(--n-border);
  border-top-color: var(--n-accent);
}


/* ---- 11. Colour discovery strip ---------------------------------------- */

body[data-skin="noir"] .color-discovery {
  background: var(--n-ink-1);
  border-block: 1px solid var(--n-border);
}
body[data-skin="noir"] .color-discovery::after { background: var(--n-grad-line); opacity: .4; }
body[data-skin="noir"] .color-discovery-heading {
  font-family: var(--n-font-display);
  color: var(--n-fg);
}
body[data-skin="noir"] .color-discovery-sub { color: var(--n-text-muted); }
body[data-skin="noir"] .color-chip {
  background: var(--n-surface-2);
  border: 1px solid var(--n-border);
  color: var(--n-text);
  box-shadow: none;
}
body[data-skin="noir"] .color-chip:hover {
  background: var(--n-surface-hover);
  border-color: var(--n-accent);
  box-shadow: var(--n-glow);
}
body[data-skin="noir"] .color-chip-dot {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}
body[data-skin="noir"] .color-chip--white .color-chip-dot {
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .35);
}


/* ---- 12. Legacy simple footer (style.css) ------------------------------ */

body[data-skin="noir"] .footer { background: var(--n-ink-1); }
body[data-skin="noir"] .footer-link { color: var(--n-text-muted); }
body[data-skin="noir"] .footer-link:hover { color: var(--n-fg); }
body[data-skin="noir"] .footer-dot { background: var(--n-fg-3); }
body[data-skin="noir"] .footer-credit,
body[data-skin="noir"] .footer-credit a { color: var(--n-text-dim); }


/* ---- 13. Colour-search band (.csh) ------------------------------------- */
/* Rebuilt for noir. The old shape — a tall cream card holding a 64px circular
   thumbnail, a label and a decorative radio dot — reads as a form control, not
   as photography. Here each colour becomes a full-bleed photographic tile:
   the thumbnail fills the card, a wash in that colour sits over it, and the
   label rides on the image.

   All of this is CSS only. The hook that makes it possible is data-color on
   .csh-card (inc/footer.php:191), which lets every tile carry its own accent
   without a single change to the markup — so the Classic and Immersive skins
   are untouched. The hex values below are the same ones $cshHex already
   supplies inline (inc/footer.php:25-29); they are repeated here because an
   inline background-color cannot be read back out for use in a ring or a dot. */

body[data-skin="noir"] .csh {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(139, 92, 246, .07), transparent 60%),
    var(--n-ink-1);
  border-top: 1px solid var(--n-border);
  /* Tighter than the base 64px. The tiles carry the weight now, so the band
     does not need the whitespace — and this block sits in the footer of every
     page, so its height is a cost paid site-wide. */
  padding-block: clamp(36px, 4vw, 60px);
}

body[data-skin="noir"] .csh-frame {
  position: relative;
  border-radius: var(--n-r-xl);
  background: rgba(255, 255, 255, .015);
  padding: clamp(24px, 2.5vw, 38px);
}
/* Gradient hairline border, drawn with a masked padding-box so it stays 1px
   at every corner radius. */
body[data-skin="noir"] .csh-frame::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--n-grad-soft);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
  opacity: .8;
}

/* The corner ticks belong to the old framed-certificate look. */
body[data-skin="noir"] .csh-corner { display: none; }

body[data-skin="noir"] .csh-head { margin-bottom: clamp(20px, 2.2vw, 32px); }

body[data-skin="noir"] .csh-title {
  font-family: var(--n-font-display);
  font-size: var(--n-fz-2xl);
  font-weight: var(--n-fw-bold);
  letter-spacing: -.02em;
  color: var(--n-fg);
  margin-bottom: var(--n-s3);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  body[data-skin="noir"] .csh-title {
    background: var(--n-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
body[data-skin="noir"] .csh-sub {
  color: var(--n-text-muted);
  font-size: var(--n-fz-base);
}


/* --- The tiles --- */

/* The base grid puts all twelve colours on one row, which at a 1320px frame
   leaves each tile 92px wide — too narrow for a photograph to read as
   anything. Six across in two rows gives each tile ~210px and, because the
   tiles turn landscape, the band ends up the same height as before.
   These take over the base file's own breakpoints: those selectors are 0-1-0
   and these are 0-2-1, so specificity decides regardless of load order
   (footer-redesign.css is linked from the body, i.e. after this file). */
body[data-skin="noir"] .csh-cards {
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  margin-bottom: clamp(20px, 2.2vw, 30px);
}

body[data-skin="noir"] .csh-card {
  position: relative;
  display: block;
  /* min-height stays at 0: a min-height that bites would be transferred back
     through aspect-ratio and change the tile's width. */
  aspect-ratio: 3 / 2;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--n-r-md);
  border: 1px solid var(--n-border);
  background: var(--n-ink-2);
  transition: transform var(--n-dur) var(--n-ease),
              box-shadow var(--n-dur) var(--n-ease),
              border-color var(--n-dur) var(--n-ease);
}

/* The thumbnail stops being a circle and becomes the tile. Both states are
   covered: with a photo the inline background-image shows, without one the
   inline background-color does (.csh-swatch--solid). */
body[data-skin="noir"] .csh-swatch {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: auto;
  height: auto;
  border-radius: 0;
  background-size: cover;
  background-position: center;
  box-shadow: none;
  filter: brightness(.62) saturate(1.1);
  transform: scale(1.03);
  transition: filter var(--n-dur-slow) var(--n-ease),
              transform var(--n-dur-slow) var(--n-ease-emph);
}
body[data-skin="noir"] .csh-swatch--solid {
  box-shadow: none;
  filter: none;
}

/* Colour wash — this is what makes a tile read as "green" or "red" even when
   the photograph behind it is busy. */
body[data-skin="noir"] .csh-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--csh-tint, var(--n-violet));
  opacity: .30;
  mix-blend-mode: soft-light;
  pointer-events: none;
  transition: opacity var(--n-dur) var(--n-ease);
}

/* Scrim under the label. */
body[data-skin="noir"] .csh-card::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 62%;
  z-index: 2;
  background: linear-gradient(to top,
                rgba(8, 8, 10, .92) 0%,
                rgba(8, 8, 10, .45) 45%,
                rgba(8, 8, 10, 0) 100%);
  pointer-events: none;
}

body[data-skin="noir"] .csh-label {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 3;
  display: block;
  max-width: none;
  padding: 10px 6px 12px;
  text-align: center;
  font-family: var(--n-font-display);
  font-size: var(--n-fz-sm);
  font-weight: var(--n-fw-semi);
  color: var(--n-fg);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .85);
  transition: transform var(--n-dur) var(--n-ease);
}

/* The old radio dot becomes a colour pin: the one place the true swatch
   colour is shown undiluted, so the tile stays honest about what it filters. */
body[data-skin="noir"] .csh-radio {
  position: absolute;
  z-index: 3;
  top: 10px;
  inset-inline-end: 10px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--csh-tint, var(--n-violet));
  border: 1px solid rgba(255, 255, 255, .55);
  box-shadow: 0 0 0 3px rgba(8, 8, 10, .45);
  transition: transform var(--n-dur) var(--n-ease-back),
              box-shadow var(--n-dur) var(--n-ease);
}

/* --- Interaction --- */

body[data-skin="noir"] .csh-card:hover,
body[data-skin="noir"] .csh-card:focus-visible {
  transform: translateY(-6px);
  border-color: transparent;
  box-shadow: 0 0 0 1px var(--csh-tint, var(--n-accent)),
              0 18px 40px -12px rgba(0, 0, 0, .8),
              var(--n-glow);
}
body[data-skin="noir"] .csh-card:hover .csh-swatch,
body[data-skin="noir"] .csh-card:focus-visible .csh-swatch {
  filter: brightness(1.02) saturate(1.05);
  transform: scale(1.1);
}
body[data-skin="noir"] .csh-card:hover::before,
body[data-skin="noir"] .csh-card:focus-visible::before { opacity: .10; }

body[data-skin="noir"] .csh-card:hover .csh-label,
body[data-skin="noir"] .csh-card:focus-visible .csh-label { transform: translateY(-2px); }

body[data-skin="noir"] .csh-card:hover .csh-radio,
body[data-skin="noir"] .csh-card:focus-visible .csh-radio {
  transform: scale(1.3);
  box-shadow: 0 0 0 3px rgba(8, 8, 10, .45), 0 0 14px 2px var(--csh-tint, var(--n-accent));
}

body[data-skin="noir"] .csh-card:focus-visible {
  outline: 2px solid var(--n-fg);
  outline-offset: 3px;
}
body[data-skin="noir"] .csh-card:active { transform: translateY(-2px); }


/* --- Per-colour accent, from data-color on .csh-card ---
   Same values as $cshHex in inc/footer.php:25-29. */

body[data-skin="noir"] .csh-card[data-color="White"]  { --csh-tint: #f5f5f0; }
body[data-skin="noir"] .csh-card[data-color="Gray"]   { --csh-tint: #9aa0a6; }
body[data-skin="noir"] .csh-card[data-color="Black"]  { --csh-tint: #1a1a1a; }
body[data-skin="noir"] .csh-card[data-color="Brown"]  { --csh-tint: #7a4a2c; }
body[data-skin="noir"] .csh-card[data-color="Pink"]   { --csh-tint: #f0b6c4; }
body[data-skin="noir"] .csh-card[data-color="Purple"] { --csh-tint: #8a73c8; }
body[data-skin="noir"] .csh-card[data-color="Blue"]   { --csh-tint: #3a7bb8; }
body[data-skin="noir"] .csh-card[data-color="Cyan"]   { --csh-tint: #5fb6b6; }
body[data-skin="noir"] .csh-card[data-color="Green"]  { --csh-tint: #5a9a4a; }
body[data-skin="noir"] .csh-card[data-color="Yellow"] { --csh-tint: #e5b94a; }
body[data-skin="noir"] .csh-card[data-color="Orange"] { --csh-tint: #d97a3a; }
body[data-skin="noir"] .csh-card[data-color="Red"]    { --csh-tint: #c33b3b; }

/* Black and White are the two that a soft-light wash cannot express — one
   would vanish, the other would blow the photo out. They get a border
   treatment instead. */
body[data-skin="noir"] .csh-card[data-color="Black"]::before {
  mix-blend-mode: normal;
  background: linear-gradient(to top, rgba(0, 0, 0, .55), rgba(0, 0, 0, .15));
  opacity: 1;
}
body[data-skin="noir"] .csh-card[data-color="Black"]:hover::before { opacity: .45; }
body[data-skin="noir"] .csh-card[data-color="White"]::before {
  mix-blend-mode: normal;
  background: linear-gradient(to top, rgba(245, 245, 240, .16), rgba(245, 245, 240, .04));
  opacity: 1;
}
body[data-skin="noir"] .csh-card[data-color="White"]:hover::before { opacity: .5; }
body[data-skin="noir"] .csh-card[data-color="Black"] .csh-radio {
  border-color: rgba(255, 255, 255, .75);
}


/* --- CTA --- */

body[data-skin="noir"] .csh-cta {
  background: var(--n-grad);
  border: 0;
  color: var(--n-on-accent);
  -webkit-text-fill-color: var(--n-on-accent);
  font-family: var(--n-font-display);
  font-weight: var(--n-fw-bold);
  padding: 15px 32px;
  box-shadow: none;
}
body[data-skin="noir"] .csh-cta:hover {
  background: var(--n-grad);
  filter: brightness(1.08);
  box-shadow: var(--n-glow);
  transform: translateY(-2px);
}
body[data-skin="noir"] .csh-cta:focus-visible {
  outline: 2px solid var(--n-fg);
  outline-offset: 3px;
}
body[data-skin="noir"] .csh-cta-icon { color: var(--n-on-accent); }


/* --- Responsive --- */
/* The base file already steps the column count down (12 → 6 → 4 → 3); only
   the tile proportions need easing so they do not get tall and thin. */

@media (max-width: 899px) {
  body[data-skin="noir"] .csh-cards { grid-template-columns: repeat(4, 1fr); }
  body[data-skin="noir"] .csh-card { aspect-ratio: 4 / 3; }
}
@media (max-width: 599px) {
  body[data-skin="noir"] .csh-cards { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  body[data-skin="noir"] .csh-card { aspect-ratio: 1 / 1; border-radius: var(--n-r-sm); }
  body[data-skin="noir"] .csh-label { font-size: var(--n-fz-xs); padding: 8px 4px 9px; }
  body[data-skin="noir"] .csh-radio { width: 9px; height: 9px; top: 7px; inset-inline-end: 7px; }
  /* No hover on touch — keep the tiles readable at rest instead. */
  body[data-skin="noir"] .csh-swatch { filter: brightness(.7) saturate(1.1); }
  body[data-skin="noir"] .csh-card:hover { transform: none; box-shadow: none; border-color: var(--n-border); }
  body[data-skin="noir"] .csh-card:active { transform: scale(.97); }
}

@media (prefers-reduced-motion: reduce) {
  body[data-skin="noir"] .csh-card,
  body[data-skin="noir"] .csh-swatch,
  body[data-skin="noir"] .csh-label,
  body[data-skin="noir"] .csh-radio,
  body[data-skin="noir"] .csh-card::before { transition: none; }
  body[data-skin="noir"] .csh-card:hover { transform: none; }
  body[data-skin="noir"] .csh-card:hover .csh-swatch { transform: scale(1.03); }
  body[data-skin="noir"] .csh-card:hover .csh-radio { transform: none; }
}

/* ---- 14. Site footer (.sfd) -------------------------------------------- */
/* Already dark; retinted from warm espresso/gold to the noir ink + chroma. */

body[data-skin="noir"] .sfd {
  background:
    radial-gradient(circle at 30% 20%, rgba(255, 61, 139, .05), transparent 60%),
    radial-gradient(circle at 70% 80%, rgba(139, 92, 246, .05), transparent 60%),
    var(--n-ink-1);
  color: var(--n-text);
  border-top: 1px solid transparent;
  border-image: var(--n-grad-line) 1;
}

body[data-skin="noir"] .sfd-art { color: var(--n-violet); opacity: .10; }

body[data-skin="noir"] .sfd-inner { max-width: var(--n-maxw); }

body[data-skin="noir"] .sfd-grid > .sfd-col + .sfd-col:not(.sfd-col--quick) {
  border-inline-start-color: var(--n-border);
}

body[data-skin="noir"] .sfd-h,
body[data-skin="noir"] .sfd .sfd-h {
  font-family: var(--n-font-display);
  font-weight: var(--n-fw-semi);
  color: var(--n-fg);
  letter-spacing: var(--n-tracking-wide);
}

body[data-skin="noir"] .sfd-list a,
body[data-skin="noir"] .sfd-quick a { color: var(--n-text-muted); }
body[data-skin="noir"] .sfd-list a:hover,
body[data-skin="noir"] .sfd-quick a:hover { color: var(--n-fg); }
body[data-skin="noir"] .sfd-list a:focus-visible,
body[data-skin="noir"] .sfd-quick a:focus-visible {
  outline: 2px solid var(--n-accent);
  outline-offset: 2px;
  color: var(--n-fg);
}

body[data-skin="noir"] .sfd-disabled,
body[data-skin="noir"] .sfd-quick-disabled { color: var(--n-text-dim); }

body[data-skin="noir"] .sfd-tagline { color: var(--n-text-muted); }
body[data-skin="noir"] .sfd-copy { color: var(--n-text-dim); }

body[data-skin="noir"] .sfd-social a {
  border: 1px solid var(--n-border-strong);
  color: var(--n-text-muted);
}
body[data-skin="noir"] .sfd-social a:hover {
  background: rgba(255, 61, 139, .10);
  border-color: var(--n-accent);
  color: var(--n-fg);
}
body[data-skin="noir"] .sfd-social a:focus-visible {
  outline: 2px solid var(--n-accent);
  outline-offset: 2px;
}

body[data-skin="noir"] .sfd-col--quick {
  background: rgba(255, 255, 255, .02);
  border: 1px solid var(--n-border);
  border-radius: var(--n-r-md);
}
body[data-skin="noir"] .sfd-quick > li + li { border-top-color: var(--n-border); }
body[data-skin="noir"] .sfd-qi { color: var(--n-accent); }
body[data-skin="noir"] .sfd-quick-disabled .sfd-qi { color: var(--n-fg-3); }
body[data-skin="noir"] .sfd-quick a::after { color: var(--n-accent); }
body[data-skin="noir"] .sfd-base { border-top-color: var(--n-border); }

body[data-skin="noir"] .sfd-logo-link:focus-visible {
  outline: 2px solid var(--n-accent);
  outline-offset: 4px;
}


/* ---- 15. Maintenance banner -------------------------------------------- */
/* The banner's own <style> is inline in inc/header.php (specificity 0-1-0);
   the prefix here is 0-2-1, so no !important is needed. */

body[data-skin="noir"] .maint-soft-banner {
  background: rgba(255, 180, 61, .10);
  border-bottom: 1px solid rgba(255, 180, 61, .40);
  color: var(--n-warning);
  font-family: var(--n-font-body);
}
body[data-skin="noir"] .maint-soft-ret { color: rgba(255, 180, 61, .75); }
body[data-skin="noir"] .maint-soft-close { color: var(--n-warning); }


/* ---- 16. Focus, skip link, misc ---------------------------------------- */

body[data-skin="noir"] :where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--n-accent);
  outline-offset: 2px;
  border-radius: var(--n-r-xs);
}

body[data-skin="noir"] .skip-link {
  background: var(--n-grad);
  color: var(--n-on-accent);
  border-radius: var(--n-r-pill);
  box-shadow: var(--n-sh-2);
}

/* accessibility/assets/accessibility.css is a deliberately self-insulated
   island — it pins its own color-scheme, tokens and font with !important so
   the toolbar stays predictable and maximally legible no matter what the page
   does. The skin leaves it alone on purpose. */


/* ---- 17. Error + statement pages (no page_css of their own) ------------- */

body[data-skin="noir"] .a11y-statement-page { color: var(--n-text); }
body[data-skin="noir"] .a11y-statement-body { line-height: var(--n-lh-read); }
body[data-skin="noir"] .a11y-statement-body h2,
body[data-skin="noir"] .a11y-statement-body h3 { font-family: var(--n-font-display); }
body[data-skin="noir"] .a11y-statement-body a { color: var(--n-accent); }

body[data-skin="noir"] .card.text-center { background: var(--n-surface); }


/* ---- 18. Motion --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  body[data-skin="noir"] .nav-link::after,
  body[data-skin="noir"] .btn,
  body[data-skin="noir"] .gallery-tile img,
  body[data-skin="noir"] .csh-card,
  body[data-skin="noir"] .csh-cta,
  body[data-skin="noir"] .color-chip { transition: none; }

  body[data-skin="noir"] .btn:hover,
  body[data-skin="noir"] .csh-card:hover,
  body[data-skin="noir"] .csh-cta:hover,
  body[data-skin="noir"] .color-chip:hover { transform: none; }

  body[data-skin="noir"] .gallery-tile:hover img { transform: none; }
}
