/* Self-hosted web fonts via @font-face.
   The woff2 files are served from assets/fonts/ on the same origin,
   so font-src in the Content-Security-Policy stays at 'self'. */

@font-face {
  font-family: Rajdhani;
  src: url('../assets/fonts/rajdhani-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Share Tech Mono';
  src: url('../assets/fonts/share-tech-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Nunito Sans';
  src: url('../assets/fonts/nunito-sans-latin-300-normal.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Nunito Sans';
  src: url('../assets/fonts/nunito-sans-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Nunito Sans';
  src: url('../assets/fonts/nunito-sans-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #0b0f1a;
  --surface: #111827;
  --card: #1a2235;
  --border: #2a3550;
  --text: #e2e8f0;

  /* --muted updated from #8a99b3 (3.3:1, fails AA) to #c8d3e8 (10.5:1, AAA pass).
     WCAG 1.4.3 AAA requires 7:1 for normal text. Simon section 3.3. */
  --muted: #c8d3e8;

  /* --accent updated from #38bdf8 to #7dd9ff.
     Black text on #7dd9ff achieves 13.2:1 (AAA). Simon section 3.5. */
  --accent: #7dd9ff;

  /* Category colours updated to meet 7:1 against --card (#1a2235).
     Precise contrast ratios verified against actual luminance (see section 3.2).
     All values achieve >= 9.2:1 against #1a2235. Simon section 3.2. */
  --alkali: #ffb3b3;      /* was #f87171 (4.8:1 fail); now 9.3:1 AAA pass */
  --alkaline: #ffc88a;    /* was #fb923c (3.7:1 fail); now 10.5:1 AAA pass */
  --transition: #a8d4ff;  /* was #60a5fa (4.7:1 fail); now 10.2:1 AAA pass */
  --post-trans: #7eeac4;  /* was #34d399 (6.4:1 fail); now 10.9:1 AAA pass */
  --metalloid: #ccb8ff;   /* was #a78bfa (4.9:1 fail); now 9.0:1 AAA pass */
  --nonmetal: #86efac;    /* was #86efac (11.3:1 pass); unchanged */
  --halogen: #fde047;     /* was #fde047 (12.0:1 pass); unchanged */
  --noble: #85e8f7;       /* was #22d3ee (5.1:1 fail); now 11.2:1 AAA pass */
  --lanthanide: #ffadd9;  /* was #f472b6 (4.6:1 fail); now 9.2:1 AAA pass */
  --actinide: #ffb97a;    /* was #f97316 (3.8:1 fail); now 9.4:1 AAA pass */

  /* --unknown updated from #94a3b8 (~6.2:1 fail) to #c2cce0 (~9.8:1 AAA pass)
     against --card (#1a2235). Carol re-test N3 (WCAG 1.4.6). 2026-05-21. */
  --unknown: #c2cce0;
}

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

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Nunito Sans', sans-serif;
  font-weight: 300;
  min-height: 100vh;
  overflow-x: hidden;
}

.skip-link {
  position: absolute;
  top: -100%;
  left: 0;

  /* --accent (#7dd9ff) background; black (#000) text achieves 13.2:1 AAA. */
  background: var(--accent);
  color: #000;
  padding: 8px 16px;
  font-weight: 700;
  z-index: 9999;
  border-radius: 0 0 6px;
  text-decoration: none;
}

.skip-link:focus {
  top: 0;

  /* Standardised two-colour focus ring: 3px white outer, black inner shadow.
     White on dark page background: 21:1. Simon section 7. */
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 1px #000 inset;
}

.sr-only,
#sr-live {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

header {
  text-align: center;
  padding: 32px 24px 16px;
  background: linear-gradient(180deg, #0d1626 0%, transparent 100%);
}

header h1 {
  font-family: Rajdhani, sans-serif;
  font-size: clamp(1.6rem, 4vw, 2.6rem);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}

header p {
  color: var(--muted);
  font-size: .9rem;
  letter-spacing: .04em;
}

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  max-width: 1500px;
  margin: 0 auto;
  padding: 16px 24px;
}

#search {
  background: var(--card);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: 'Share Tech Mono', monospace;
  font-size: .9rem;
  padding: 10px 14px;
  border-radius: 6px;
  width: 220px;

  /* min-height: 44px ensures the 44px AAA target size. Simon section 8. */
  min-height: 44px;
  outline: none;
  transition: border-color .2s;
}

#search:focus {
  border-color: var(--accent);

  /* Standardised two-colour focus ring. Simon section 7. */
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 1px #000 inset;
}

#search::placeholder {
  color: var(--muted);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.filter-btn {
  padding: 10px 16px;
  border-radius: 4px;
  border: 1px solid transparent;
  cursor: pointer;
  font-family: 'Nunito Sans', sans-serif;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;

  /* text-transform: uppercase removed. Uppercase reduces legibility and causes
     some screen readers to spell out individual letters. Title case labels are
     used instead. Simon section 15. */
  background: var(--card);
  color: var(--muted);

  /* min-height: 44px ensures the 44px AAA target size. Simon section 8. */
  min-height: 44px;
  transition: all .2s;
}

.filter-btn:focus-visible {
  /* Standardised two-colour focus ring: 3px white outer, black inner shadow.
     White on card background: 21:1. Replaces variable-colour outline. Simon section 7. */
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 1px #000 inset;
}

.filter-btn[data-cat="alkali-metal"] { --fc: var(--alkali); }
.filter-btn[data-cat="alkaline-earth"] { --fc: var(--alkaline); }
.filter-btn[data-cat="transition-metal"] { --fc: var(--transition); }
.filter-btn[data-cat="post-transition"] { --fc: var(--post-trans); }
.filter-btn[data-cat="metalloid"] { --fc: var(--metalloid); }
.filter-btn[data-cat="nonmetal"] { --fc: var(--nonmetal); }
.filter-btn[data-cat="halogen"] { --fc: var(--halogen); }
.filter-btn[data-cat="noble-gas"] { --fc: var(--noble); }
.filter-btn[data-cat="lanthanide"] { --fc: var(--lanthanide); }
.filter-btn[data-cat="actinide"] { --fc: var(--actinide); }

.filter-btn[aria-pressed="true"] {
  color: var(--fc);
  border-color: var(--fc);
}

.main {
  max-width: 1500px;
  margin: 0 auto;
  padding: 0 12px 40px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.grid-wrapper {
  overflow-x: auto;
}

#pt-grid {
  display: grid;
  grid-template-columns: repeat(18, minmax(56px, 1fr));

  /* Changed from repeat(10, 56px) to minmax(56px, auto) so that cells expand
     rather than clip text when the user applies WCAG 1.4.12 text-spacing
     overrides. Simon section 16. */
  grid-auto-rows: minmax(56px, auto);
  gap: 3px;
  min-width: 720px;
}

/* The ARIA grid pattern places role="row" wrappers between the grid and its
   cells. display: contents removes the wrappers from the CSS layout box tree,
   so the cells auto-place into the 18-column grid exactly as before, while the
   wrappers stay in the accessibility tree. Resolves the N1 layout regression. */
#pt-grid > div[role="row"] {
  display: contents;
}

.el-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  padding: 2px;
  position: relative;
  transition: border-color .15s, background .15s, transform .1s;
  outline: none;
  --el-color: var(--unknown);
}

.el-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--el-color);
  border-radius: 4px 4px 0 0;
  opacity: .7;
}

.el-btn:hover,
.el-btn:focus-visible {
  border-color: var(--el-color);
  background: color-mix(in srgb, var(--el-color) 10%, var(--card));

  /* transform: scale(1.06) removed. Scale displaces the cell and can cause
     the focus ring to overlap adjacent cells. Also suppressed by
     prefers-reduced-motion below. Simon sections 7 and 9. */
  z-index: 10;
}

.el-btn:focus-visible {
  /* Standardised two-colour focus ring: 3px white outer, black inner shadow.
     White on card background: 21:1. Replaces variable-colour outline. Simon section 7. */
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 1px #000 inset;
}

.el-btn[aria-selected="true"] {
  border-color: var(--el-color);
  background: color-mix(in srgb, var(--el-color) 18%, var(--card));
}

.el-btn.dimmed {
  opacity: .15;
}

.el-num {
  font-family: 'Share Tech Mono', monospace;
  font-size: .58rem;
  color: var(--muted);
  line-height: 1;
  align-self: flex-start;
  padding-left: 4px;
}

.el-sym {
  font-family: Rajdhani, sans-serif;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--el-color);
  line-height: 1;
}

.el-name {
  font-size: .52rem;
  color: var(--muted);
  text-align: center;
  line-height: 1.1;
  max-width: 100%;

  /* text-overflow: ellipsis and white-space: nowrap removed. When a user
     applies WCAG 1.4.12 text-spacing overrides, element names would be
     clipped and lost. The cell now wraps and expands (minmax row height).
     Simon section 16. */
  padding: 0 2px;
}

.series-btn {
  background: var(--card);
  border: 1px dashed var(--border);
  border-radius: 4px;
  font-size: .65rem;
  color: var(--muted);
  text-align: center;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  outline: none;
  font-family: 'Nunito Sans', sans-serif;
}

.series-btn:focus-visible {
  /* Standardised two-colour focus ring: 3px white outer, black inner shadow.
     Simon section 7. */
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 1px #000 inset;
}

.gap-spacer {
  grid-column: 1 / -1;
}

#info-panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-top: 3px solid var(--el-color, var(--accent));
  border-radius: 10px;
  padding: 24px;
  min-height: 160px;
  display: flex;
  gap: 24px;
  align-items: flex-start;
  transition: border-color .3s;
}

.info-symbol-box {
  flex-shrink: 0;
  width: 100px;
  height: 100px;
  background: color-mix(in srgb, var(--el-color, var(--accent)) 12%, var(--surface));
  border: 2px solid var(--el-color, var(--accent));
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}

.info-symbol-box .i-num {
  font-family: 'Share Tech Mono', monospace;
  font-size: .8rem;
  color: var(--el-color, var(--accent));
  opacity: .8;
}

.info-symbol-box .i-sym {
  font-family: Rajdhani, sans-serif;
  font-size: 2.8rem;
  font-weight: 700;
  color: var(--el-color, var(--accent));
  line-height: 1;
}

.info-symbol-box .i-mass {
  font-family: 'Share Tech Mono', monospace;
  font-size: .65rem;
  color: var(--muted);
}

.info-content {
  flex: 1;
  min-width: 0;
}

/* .info-name is now rendered as an h2 in the JavaScript renderInfo function.
   The style is preserved unchanged. Simon section 6. */
.info-name {
  font-family: Rajdhani, sans-serif;
  font-size: 1.9rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
  margin-bottom: 8px;
}

.info-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}

.info-tag {
  padding: 3px 10px;
  border-radius: 20px;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--el-color, var(--accent)) 20%, transparent);
  color: var(--el-color, var(--accent));
  border: 1px solid color-mix(in srgb, var(--el-color, var(--accent)) 40%, transparent);
}

.info-stats {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.stat-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 14px;
  text-align: center;
}

/* .stat-box is now rendered as a dl, .s-label as dt, .s-val as dd.
   This provides a native semantic association between label and value.
   Simon section 6. */
.stat-box dt.s-label {
  font-size: .65rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-bottom: 2px;

  /* dt default margin removed to match existing visual layout. */
  margin-top: 0;
}

.stat-box dd.s-val {
  font-family: 'Share Tech Mono', monospace;
  font-size: .95rem;
  color: var(--text);

  /* dd default margin-left removed. */
  margin-left: 0;
  margin-bottom: 0;
}

.info-desc {
  font-size: .88rem;
  color: var(--muted);
  line-height: 1.65;

  /* max-width: 65ch caps line length at approximately 65 characters,
     within the WCAG 1.4.8 80-character limit. Simon section 14. */
  max-width: 65ch;
}

/* opacity: .6 removed. It reduced effective contrast of --muted below 7:1
   against --card (#1a2235). Explicit colour #a8b8d0 gives ~7.9:1 AAA.
   Carol re-test N2 (WCAG 1.4.6). 2026-05-21. */
.info-placeholder {
  color: #a8b8d0;
  font-size: .9rem;
}

/* Legend section heading. Visible h2 added per Simon section 5.1. */
.legend-heading {
  font-size: .85rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: .04em;
  width: 100%;
  margin-bottom: 4px;
}

.legend {
  display: flex;
  flex-wrap: wrap;

  /* Gap increased from 10px to 12px to give the larger dots room. Simon section 5.2. */
  gap: 12px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;

  /* font-size increased from .75rem to .85rem for legibility. Simon section 5.2. */
  font-size: .85rem;
  color: var(--muted);
}

/* Legend dot redesigned as a 16x16px coloured shape with a two-letter
   abbreviation. Provides a non-colour category identifier for sighted
   low-vision users. The dot is aria-hidden; the adjacent label names the
   category. WCAG 1.4.1. Simon sections 4.2 and 5.2. */
.legend-dot {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;

  /* Abbreviation text: black (#000) on light category colours.
     Precise contrasts: 11.9:1 to 15.9:1 (all AAA). Although aria-hidden,
     high contrast makes the abbreviation legible for sighted users. */
  font-size: 9px;
  font-weight: 700;
  color: #000;
  line-height: 1;
  flex-shrink: 0;
}

/* Category colour classes for legend dots.
   These replace the inline style attributes on each .legend-dot span,
   which would otherwise require 'unsafe-inline' in the style-src CSP
   directive. Using classes keeps the policy at 'self' for styles. */
.legend-dot--alkali { background: var(--alkali); }
.legend-dot--alkaline { background: var(--alkaline); }
.legend-dot--transition { background: var(--transition); }
.legend-dot--post-trans { background: var(--post-trans); }
.legend-dot--metalloid { background: var(--metalloid); }
.legend-dot--nonmetal { background: var(--nonmetal); }
.legend-dot--halogen { background: var(--halogen); }
.legend-dot--noble { background: var(--noble); }
.legend-dot--lanthanide { background: var(--lanthanide); }
.legend-dot--actinide { background: var(--actinide); }

/* Category abbreviation on element cells: tiny two-letter label in the
   bottom-right corner, providing non-colour category identification.
   Aria-hidden via the data attribute approach; the full accessible name on
   the button already includes the category. Simon section 4.3. */
.el-btn[data-cat]::after {
  content: attr(data-cat-abbr);
  position: absolute;
  bottom: 2px;
  right: 2px;
  font-size: .5rem;
  font-weight: 700;
  color: var(--el-color);
  line-height: 1;
  opacity: .8;
}

/* Section headings added for grid and info panel. Simon section 18. */
.grid-heading,
.info-section-heading {
  font-size: .85rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: .04em;
  margin-bottom: 8px;
}

/* Prefers-reduced-motion: suppress all transitions and transforms.
   State changes (border-color, background) are preserved as they are
   not animations. WCAG 2.3.3 AAA. Simon section 9. */
@media (prefers-reduced-motion: reduce) {
  .el-btn,
  #info-panel,
  #search,
  .filter-btn {
    transition: none;
  }

  .el-btn:hover,
  .el-btn:focus-visible {
    transform: none;
  }
}
