/* =============================================================
   styles.css  -  Orbital Visualiser, appearance only.
   Maps components onto the Lavender + Willow tokens in
   design-system.css (linked first). Colours are defined ONLY in
   the token blocks directly below; everything else uses var().

   Layout: three cards side by side on a wide screen
     1 Energy diagram | 2 Quantum numbers | 3 Orbital viewer (sticky)
   two columns on a tablet (viewer sticky on the right), and one
   column on a phone, where the viewer is docked to the bottom of
   the screen so it stays visible while an orbital is chosen above.

   Roles: lavender = primary / interactive, willow = positive
   (ground state OK). One saturated element per view: the active
   "Select by" segment. Every selection state also differs in
   border style / marker glyph, so none relies on colour alone.
   Each shell n = 1..5 has one colour hue, but "n=3" is always
   printed as text too.
   ============================================================= */

:root {
  /* wavefunction sign. Lavender vs amber: differ in hue AND lightness
     (dark violet vs light amber), so they stay distinct for red/green
     colour-blind users. app.js reads --orbital-pos / --orbital-neg. */
  --amber-400: #e59a2b;
  --phase-pos: var(--lav-700);
  --phase-neg: var(--amber-400);
  --orbital-pos: var(--phase-pos);
  --orbital-neg: var(--phase-neg);

  --viewer-bg: var(--lav-50);
  --box-bg: var(--card);
  --electron: var(--ink);
  --axis-color: var(--ink-2);

  /* ---------------------------------------------------------------
     SHELL COLOUR CODING  (n = 1..5, one hue per shell, used everywhere
     that shell appears: row rule + tint, n-tag, selection title,
     n value, legend chip). Hues walk the Lavender + Willow family and
     alternate light/dark so neighbouring shells also differ in
     lightness (not hue alone):
        n=1 lavender   n=2 willow green   n=3 rose   n=4 amber   n=5 sky
     --shell-N        rule / border / fill  (>= 3:1 on the card)
     --shell-N-soft   row & chip tint       (text on it stays AA)
     --shell-N-ink    text on soft or card  (>= 4.5:1 on both)
     Contrast (light): ink/soft 5.9-7.1, strong/card 3.5-5.5.
     Contrast (dark):  ink/soft 9.6-10.8, strong/card 6.3-10.5.
     --------------------------------------------------------------- */
  --shell-1: var(--lav-500);   --shell-1-soft: #f1e9ff;  --shell-1-ink: #5a3a9a;
  --shell-2: var(--grn-600);   --shell-2-soft: #e9f9e6;  --shell-2-ink: #2f6a32;
  --shell-3: #b83f7c;          --shell-3-soft: #fdecf4;  --shell-3-ink: #932c5f;
  --shell-4: #b8721f;          --shell-4-soft: #fdf3e3;  --shell-4-ink: #7a4a0f;
  --shell-5: #2f7fb8;          --shell-5-soft: #e6f3fc;  --shell-5-ink: #1c5f90;

  /* tooltip bubble: deep lavender in both themes, so it separates from any card */
  --tip-bg: var(--lav-900);
  --tip-ink: var(--lav-50);       /* 11.9:1 on --lav-900 */
  --tip-line: var(--lav-400);

  /* ---------------------------------------------------------------
     PERIODIC TABLE BLOCKS (s / p / d). Same three hues as shells 1, 2 and 5
     so the palette stays one family. Always paired with the block letter
     printed in the cell and in the legend, so colour is never the only cue.
     --------------------------------------------------------------- */
  --blk-s: var(--shell-1);  --blk-s-soft: var(--shell-1-soft);  --blk-s-ink: var(--shell-1-ink);
  --blk-p: var(--shell-2);  --blk-p-soft: var(--shell-2-soft);  --blk-p-ink: var(--shell-2-ink);
  --blk-d: var(--shell-5);  --blk-d-soft: var(--shell-5-soft);  --blk-d-ink: var(--shell-5-ink);

  /* layout */
  --page-max: 1480px;
  --pad-x: var(--sp-4);           /* side gutter of the app bar and every screen */
  --bar-h: 52px;                  /* slim app bar */
  --sticky-top: 12px;
  --box: 48px;                    /* orbital box height; the fit layout recomputes it from the screen height */
  --row-gap: 4px;
  --ml-h: 14px;                   /* height reserved under a box for its m_l tag */
  --axis-h: 24px;                 /* the "Energy" axis label row */
  --leave-dur: 100ms;             /* screen change: old fades out ... (same as app.js LEAVE_MS) */
  --enter-dur: 170ms;             /* ... new fades in with a short lift (ENTER_MS); 270 ms in all, <= 280 */
  --lift: 10px;                   /* vertical travel of a screen change (<= 12px) */
  color-scheme: light;
}

[data-theme="dark"] {
  --phase-pos: var(--lav-400);
  --phase-neg: #f0c274;
  --viewer-bg: var(--lav-900);
  --axis-color: var(--ink);

  --shell-1: var(--lav-300);   --shell-1-soft: #2a2142;  --shell-1-ink: var(--lav-100);
  --shell-2: var(--grn-400);   --shell-2-soft: #1f3320;  --shell-2-ink: var(--grn-200);
  --shell-3: #e58ab4;          --shell-3-soft: #3a1c2e;  --shell-3-ink: #f6bfd6;
  --shell-4: #f0c274;          --shell-4-soft: #33260f;  --shell-4-ink: #f7d9a0;
  --shell-5: #7cc0ee;          --shell-5-soft: #14293b;  --shell-5-ink: #b7ddf7;

  --tip-line: var(--lav-300);
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --phase-pos: var(--lav-400);
    --phase-neg: #f0c274;
    --viewer-bg: var(--lav-900);
    --axis-color: var(--ink);

    --shell-1: var(--lav-300);   --shell-1-soft: #2a2142;  --shell-1-ink: var(--lav-100);
    --shell-2: var(--grn-400);   --shell-2-soft: #1f3320;  --shell-2-ink: var(--grn-200);
    --shell-3: #e58ab4;          --shell-3-soft: #3a1c2e;  --shell-3-ink: #f6bfd6;
    --shell-4: #f0c274;          --shell-4-soft: #33260f;  --shell-4-ink: #f7d9a0;
    --shell-5: #7cc0ee;          --shell-5-soft: #14293b;  --shell-5-ink: #b7ddf7;

    --tip-line: var(--lav-300);
    color-scheme: dark;
  }
}

/* No overflow on html/body: any non-visible overflow on an ancestor turns it into
   a scroll container and silently breaks position: sticky. `clip` hides a stray
   horizontal overflow without creating a scroll container. */
body { overflow-x: clip; }

button:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- real sub/superscripts: never change the line height or box size ---------- */
sub, sup {
  font-size: .72em; line-height: 0; position: relative;
  vertical-align: baseline; letter-spacing: .02em; font-style: normal;
}
sub { top: .32em; }
sup { top: -.42em; }

/* ---------- app bar: slim, the same on every screen ----------
   Home link | logo + title | ...... | mode switch | element chip | theme toggle.
   app.js shows #mode-switch and #element-chip with [hidden], depending on the screen. */
.app-bar {
  position: relative; z-index: 40; flex: none;
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
  min-height: var(--bar-h); padding: var(--sp-2) var(--pad-x);
  background: var(--bg); border-bottom: 1px solid var(--line);
  --control-h: 40px;               /* the bar's controls are one step smaller than elsewhere */
}
.app-bar .top-links { margin: 0; padding: 0; gap: 0; flex: none; }
.app-bar .home-link { font: var(--t-small); font-weight: var(--w-semi); padding: 6px 0; white-space: nowrap; }
.app-bar__brand {
  display: inline-flex; align-items: center; gap: var(--sp-2); width: auto; margin: 0; flex: none;
  text-decoration: none; color: var(--title); border-radius: var(--r-sm); line-height: 1;
}
.app-bar__brand img { height: 30px; width: auto; }
.app-bar__title { font: var(--w-display) 1.0625rem/1.2 var(--font-display); letter-spacing: var(--tr-heading); color: var(--title); white-space: nowrap; }
.app-bar__brand:hover .app-bar__title { text-decoration: underline; text-underline-offset: 3px; }
.app-bar__tools { margin-left: auto; display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); min-width: 0; }
/* the theme toggle lives in the bar here (the design system fixes it to the corner) */
.app-bar .theme-toggle { position: static; flex: none; width: 38px; height: 38px; font-size: 1.05rem; box-shadow: none; }

/* mode switch: a quiet, soft segmented control. The saturated segment of the app view is "Select by";
   the chosen mode is shown by a soft fill, a ring and a check mark, never by colour alone. */
.mode-switch { border: 0; margin: 0; padding: 0; min-width: 0; }
.mode-switch .seg { flex-wrap: nowrap; }
.mode-switch .seg > label { padding: 4px var(--sp-4); font-size: .9375rem; white-space: nowrap; }
.mode-switch .seg--strong > label:has(input:checked) {
  background: var(--primary-soft); color: var(--primary-soft-ink); box-shadow: inset 0 0 0 1px var(--primary);
}
.mode-switch .seg > label:has(input:checked)::before { content: "\2713"; margin-right: 6px; font-size: .85em; }

/* element chip: "Fe · Z = 26" + a "change" affordance */
.element-chip {
  display: inline-flex; align-items: center; gap: var(--sp-2); min-height: 38px; padding: 3px 4px 3px var(--sp-4);
  font: var(--t-body-strong); line-height: 1.2; white-space: nowrap;
  color: var(--ink); background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  cursor: pointer; transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.element-chip:hover { border-color: var(--primary); box-shadow: var(--shadow-1); }
.element-chip__text { font-variant-numeric: tabular-nums; }
.element-chip__change {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px var(--sp-3); border-radius: var(--r-pill);
  font: var(--t-small); font-weight: var(--w-semi); line-height: 1.3;
  color: var(--primary-soft-ink); background: var(--primary-soft); box-shadow: inset 0 0 0 1px var(--primary);
  transition: background-color var(--dur) var(--ease);
}
.element-chip__change::after { content: "\25BE"; font-size: .85em; }       /* small chevron: it opens the table */
.element-chip:hover .element-chip__change { background: var(--card-2); }

.site-footer {
  max-width: var(--page-max); margin: var(--sp-6) auto; padding: var(--sp-4) var(--pad-x) 0;
  border-top: 1px solid var(--line);
}
.site-footer p { color: var(--muted); }

/* ---------- screens: start | table | app. Exactly one is visible; app.js uses [hidden] for the rest ----------
   All screens share ONE grid cell, so a change never moves the page: whichever is visible (or, for a
   moment, the leaving and the entering one together) occupies the same box. The fade is vertical only
   (<= 12px lift) and never touches the width, so there is no horizontal movement or scroll; the main
   area clips the lift (overflow: clip does not make a scroll container, so the docked viewer still sticks).
   app.js also runs the same fade through the Web Animations API (motion.js, 100 ms out / 170 ms in);
   these keyframes use the same timings so the two never disagree, and cover the case without it. */
.app-main { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; overflow: clip; }
.screen { grid-area: 1 / 1; min-width: 0; min-height: 0; }
.screen :is(h1, h2, [tabindex="-1"]):focus { outline: none; box-shadow: none; }   /* programmatic focus on a heading: announced, but no ring */
.screen.is-entering { animation: screen-in var(--enter-dur) var(--ease) both; }
.screen.is-leaving { pointer-events: none; animation: screen-out var(--leave-dur) var(--ease) both; }
@keyframes screen-in  { from { opacity: 0; transform: translateY(var(--lift)); } to { opacity: 1; transform: none; } }
@keyframes screen-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: none; } }
/* reduced motion: design-system.css shrinks every animation to .01ms (animationend still fires), so
   the change is instant and the old screen ends fully transparent. */
@media (prefers-reduced-motion: reduce) {
  .screen.is-entering, .screen.is-leaving { animation-duration: .01ms !important; animation-delay: 0s !important; }
}

/* ---------- layout: one column (phone) ---------- */
.viz-layout {
  width: 100%; max-width: var(--page-max); margin: 0 auto; padding: var(--sp-2) var(--pad-x) 0;
  display: flex; flex-direction: column; gap: var(--sp-4);
}
.card { padding: var(--sp-4); min-width: 0; }

/* The viewer is docked to the bottom edge of the screen while the cards above it
   scroll past (sticky inside a plain flex column: its containing block is the
   whole layout). In its natural place it is the last card. */
#panel-viewer {
  position: sticky; bottom: var(--sp-2); z-index: 20;
  display: flex; flex-direction: column; gap: var(--sp-2);
  max-height: calc(100vh - var(--sp-4)); max-height: calc(100dvh - var(--sp-4));
  overflow-y: auto; overscroll-behavior: contain;
  box-shadow: var(--shadow-3);
}
/* docked on a phone: keep it to about 40% of the screen so the cards above stay usable */
@media (max-width: 899px) {
  #panel-viewer { padding: var(--sp-3); max-height: 56vh; max-height: 56dvh; }
  #panel-viewer .card-head { min-height: 36px; margin-bottom: 0; }
  #panel-viewer .viewer-hint, #panel-viewer .scale-readout, #panel-viewer .legend-title { display: none; }
  #panel-viewer #viewer-legend { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; padding-bottom: 4px; scrollbar-width: thin; }
  #panel-viewer .legend-item, #panel-viewer .legend-sign { flex: none; white-space: nowrap; }
  #panel-viewer .legend-item { min-height: 32px; padding: 2px 10px; }
  #panel-viewer .legend-sign { margin: 0; }
}

/* ---------- layout: two columns (tablet) - energy + quantum numbers left, viewer sticky right ---------- */
@media (min-width: 900px) {
  .viz-layout {
    display: grid; align-items: start; gap: var(--sp-5); padding: var(--sp-2) var(--sp-5) 0;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
    grid-template-areas: "diagram viewer" "info viewer";
  }
  #panel-diagram { grid-area: diagram; }
  #panel-info    { grid-area: info; }
  #panel-viewer  {
    grid-area: viewer; align-self: start;
    top: var(--sticky-top); bottom: auto;
    max-height: calc(100vh - var(--sticky-top) - var(--sp-4)); max-height: calc(100dvh - var(--sticky-top) - var(--sp-4));
    overflow: hidden;              /* the canvas always stays in view; the legend below it scrolls instead */
    box-shadow: var(--shadow-2);
  }
  #viewer-legend { flex: 0 1 auto; min-height: 4.5rem; overflow-y: auto; align-content: flex-start; scrollbar-width: thin; }
  .site-footer { padding-left: var(--sp-5); padding-right: var(--sp-5); }
  .card { padding: var(--sp-5); }
  :root { --pad-x: var(--sp-5); --box: 48px; }
}

/* ---------- layout: three columns (desktop) ---------- */
@media (min-width: 1240px) {
  .viz-layout {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr) minmax(0, 1.05fr);
    grid-template-areas: "diagram info viewer";
  }
}

/* ---------- card header: step number + title ---------- */
.card-head { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--control-h); margin-bottom: var(--sp-3); }
.card-title { font: var(--t-h2); margin: 0; flex: 1 1 auto; min-width: 0; }
.step {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font: var(--w-semi) .8125rem/1 var(--font-body); font-variant-numeric: tabular-nums;
  color: var(--primary-soft-ink); background: var(--primary-soft); border: 1px solid var(--line-strong);
}
.card-head .btn { flex: none; min-height: 36px; padding: 4px 16px; }
@media (pointer: coarse) { .card-head .btn { min-height: var(--control-h); } }

/* ---------- slice bar (segmented control) ---------- */
.slice-bar { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); margin-bottom: var(--sp-4); }
#slice-mode { border: 0; margin: 0; padding: 0; min-width: 0; max-width: 100%; }
#slice-mode legend {
  padding: 0; float: none; width: 100%; margin-bottom: var(--sp-1);
  font: var(--t-label); letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--muted);
}
.slice-hint { color: var(--muted); margin: 0; max-width: 46ch; font-size: 1rem; line-height: 1.45; }
.slice-hint:empty { display: none; }

/* ---------- shell colour hooks ----------
   Any element carrying data-n="1..5" or data-shell="1..5" gets the three locals
   --sh / --sh-soft / --sh-ink. Components below read them with a neutral fallback,
   so an element without the attribute keeps the plain lavender look.
   Hooked up: .subshell-row[data-n] (+ the orbital boxes inside it), .shell-tag[data-shell],
   #selection-title[data-shell], .qn-val[data-shell], .legend-item[data-n]. */
[data-n="1"], [data-shell="1"] { --sh: var(--shell-1); --sh-soft: var(--shell-1-soft); --sh-ink: var(--shell-1-ink); }
[data-n="2"], [data-shell="2"] { --sh: var(--shell-2); --sh-soft: var(--shell-2-soft); --sh-ink: var(--shell-2-ink); }
[data-n="3"], [data-shell="3"] { --sh: var(--shell-3); --sh-soft: var(--shell-3-soft); --sh-ink: var(--shell-3-ink); }
[data-n="4"], [data-shell="4"] { --sh: var(--shell-4); --sh-soft: var(--shell-4-soft); --sh-ink: var(--shell-4-ink); }
[data-n="5"], [data-shell="5"] { --sh: var(--shell-5); --sh-soft: var(--shell-5-soft); --sh-ink: var(--shell-5-ink); }

/* ---------- energy diagram ----------
   One row per subshell: [subshell label] [n tag] [orbital boxes]; the m_l tag hangs under its box.
   Every size derives from ONE number, --box (the box height). Scrolling layouts leave it at a fixed value
   (48px, 44px on a phone); the no-scroll "fit" layout below recomputes it from the height of the diagram
   area, so the 11 rows always add up to exactly the room the card has. */
#energy-diagram {
  --axis-pad: 44px;                /* room for the vertical energy axis */
  --row-pad: 6px;                  /* vertical padding inside a row */
  --name-zone: 15px;               /* top part of a box kept for its small orbital name */
  --name-fs: .75rem;               /* ... and its text size */
  --arrow-fs: 1.45rem;             /* electron arrow glyph */
  --ml-fs: var(--fs-label);        /* m_l tag size */
  --box-w: var(--box);             /* box width (the fit layout narrows it if a row would not fit) */
  position: relative; display: flex; flex-direction: column; gap: var(--row-gap);
  padding-left: var(--axis-pad);
}
.energy-axis {
  position: relative; display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center;
  min-height: var(--axis-h); margin: 0 0 var(--sp-1) calc(-1 * var(--axis-pad)); color: var(--muted); background: var(--card);
}
.energy-axis .energy-arrow { font: var(--t-label); color: var(--ink); letter-spacing: var(--tr-label); text-transform: uppercase; min-width: 40px; text-align: center; }
#energy-diagram::before {          /* the axis line */
  content: ""; position: absolute; left: calc(var(--axis-pad) / 2 - 1px); top: 0; bottom: 6px; width: 2px; background: var(--muted);
}
.energy-axis + .subshell-row::after {   /* its arrow head, centred on the line, tip just above the top row */
  content: ""; position: absolute; left: calc(var(--axis-pad) / -2 - 7px); top: -6px;
  border: 7px solid transparent; border-top: 0; border-bottom: 11px solid var(--muted);
}

.subshell-row {
  position: relative; display: flex; align-items: flex-start; flex-wrap: wrap; gap: 6px 8px;
  padding: var(--row-pad) 6px var(--row-pad) 10px;
  background: var(--sh-soft, var(--bg-tint));
  border-left: 5px solid var(--sh, var(--line-strong));
  border-radius: var(--r-sm);
  transition: background var(--dur) var(--ease), opacity var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.subshell-label, .shell-tag {
  flex: none; display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  height: var(--box); padding: 0 8px;
  font: var(--t-body-strong); cursor: pointer; border-radius: var(--r-sm);
  border: 1px solid var(--line-strong); background: var(--card); color: var(--ink);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.subshell-label { min-width: 48px; font-family: var(--font-display); font-size: clamp(1rem, calc(var(--box) * .4), 1.3rem); }
.shell-tag {
  min-width: 50px; font-family: var(--font-mono); font-size: clamp(.75rem, calc(var(--box) * .3), .9375rem); font-weight: var(--w-semi);
  color: var(--sh-ink, var(--muted)); border: 2px dashed var(--sh, var(--line-strong));
}
.subshell-label:hover, .shell-tag:hover { background: var(--primary-soft); border-color: var(--primary); }
.subshell-label[aria-pressed="true"], .shell-tag[aria-pressed="true"],
.subshell-label.is-selected, .shell-tag.is-selected {
  background: var(--primary-soft); color: var(--primary-soft-ink); border: 2px solid var(--primary); font-weight: var(--w-semi);
}
.subshell-label.is-context, .shell-tag.is-context { background: var(--bg-tint); }

.orbital-boxes { display: flex; flex-wrap: wrap; gap: 4px 6px; }

.orbital-box {
  position: relative; flex: none;
  width: var(--box-w); height: var(--box); padding: 0;
  margin-bottom: var(--ml-h);       /* room for the m_l tag hanging under the box */
  background: var(--box-bg); color: var(--ink);
  border: 2px solid var(--sh, var(--muted)); border-radius: var(--r-sm); cursor: pointer;
  font: inherit;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.orbital-box::before {           /* up/down half divider */
  content: ""; position: absolute; top: var(--name-zone); bottom: 4px; left: 50%; width: 0;
  border-left: 1px dashed var(--line-strong);
}
.orbital-box:hover { border-color: var(--primary); transform: translateY(-1px); }

/* the electron arrows live in the lower part of the box; the orbital name sits above them.
   Opacity is eased, so an arrow that app.js fades in or out (or marks .is-new / .is-leaving) changes softly. */
.orbital-box .electron {
  position: absolute; top: calc(var(--name-zone) - 3px); bottom: -1px; width: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 0; line-height: 1; color: var(--electron); pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.orbital-box .electron::before { font-size: var(--arrow-fs); font-weight: var(--w-semi); font-family: var(--font-body); }
.orbital-box .electron.is-new { animation: electron-in var(--dur) var(--ease) both; }   /* an electron just added fades in (opacity only: it never jumps) */
.orbital-box .electron.is-leaving { opacity: 0; }
.orbital-box .electron.is-picked { background: var(--primary-soft); box-shadow: inset 0 0 0 2px var(--primary); border-radius: var(--r-sm); }
.orbital-box .electron[data-spin="up"]   { left: 0; }
.orbital-box .electron[data-spin="down"] { right: 0; }
.orbital-box .electron[data-spin="up"]::before   { content: "\2191"; }
.orbital-box .electron[data-spin="down"]::before { content: "\2193"; }
@keyframes electron-in { from { opacity: 0; } to { opacity: 1; } }

/* text under a box: the m_l tag. Subscripts inside never grow it. */
.ml-tag {
  position: absolute; left: 50%; top: calc(100% + 4px); transform: translateX(-50%);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--ml-fs); line-height: 1.15;
  color: var(--ink-2); white-space: nowrap; pointer-events: none;
}
/* the small orbital name inside the top of every box (real <sub> inside; aria-hidden) */
.orbital-box .orbital-name, .orbital-box .box-label {
  position: absolute; left: 50%; top: 1px; transform: translateX(-50%); max-width: 100%;
  font: var(--w-semi) var(--name-fs)/var(--name-zone) var(--font-body); color: var(--ink-2); white-space: nowrap; pointer-events: none;
}
.orbital-name sub, .box-label sub { font-size: .82em; top: .3em; letter-spacing: 0; }

/* ---- orbital states: each differs in border STYLE / weight / marker, not just colour ----
   default     solid 2px, shell colour
   is-context  solid 2px, primary, tinted fill   (same subshell / shell as the selection)
   is-selected thick 4px solid + outer ring + check marker
   is-focus    double border + diamond marker    (picked inside a subshell view)
   is-dimmed   dashed border, faded              (not part of the selection)
   rows:       is-selected = solid inner frame, is-context = dashed inner frame */
.orbital-box.is-context { border-color: var(--primary); background: var(--bg-tint); }
.orbital-box.is-selected {
  border: var(--sel-bw, 4px) solid var(--primary); background: var(--primary-soft);
  box-shadow: 0 0 0 var(--ring-gap, 2px) var(--card), 0 0 0 calc(var(--ring-gap, 2px) + var(--ring-w, 2px)) var(--primary);
}
.orbital-box.is-selected::after, .orbital-box.is-focus::after {      /* corner badge: outside the box, so it never covers the name */
  position: absolute; top: calc(var(--badge, 18px) / -2 - 1px); width: var(--badge, 18px); height: var(--badge, 18px); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font: var(--w-semi) calc(var(--badge, 18px) * .66)/1 var(--font-body); color: var(--primary-soft-ink);
  background: var(--primary-soft); border: 1.5px solid var(--primary); box-sizing: border-box; pointer-events: none;
}
.orbital-box.is-selected::after { content: "\2713"; right: calc(var(--badge, 18px) / -2 - 1px); }
.orbital-box.is-focus {
  border: calc(var(--sel-bw, 4px) + 1px) double var(--primary); background: var(--primary-soft);
  box-shadow: 0 0 0 var(--ring-gap, 2px) var(--card), 0 0 0 calc(var(--ring-gap, 2px) + var(--ring-w, 2px)) var(--primary);
}
.orbital-box.is-focus::after { content: "\25C6"; left: calc(var(--badge, 18px) / -2 - 1px); font-size: calc(var(--badge, 18px) * .5); }
.orbital-box.is-dimmed:not(.is-selected):not(.is-focus):not(.is-context) { border-style: dashed; opacity: .7; }
.subshell-row.is-dimmed { background: color-mix(in srgb, var(--sh-soft, var(--bg-tint)) 55%, var(--card)); }   /* paler tint, text keeps full contrast */
.subshell-row.is-selected { box-shadow: inset 0 0 0 2px var(--primary); }
.subshell-row.is-context { outline: 2px dashed var(--primary); outline-offset: -4px; }
.subshell-row.is-dimmed .subshell-label, .subshell-row.is-dimmed .shell-tag { color: var(--ink); background: transparent; }
.subshell-row.is-dimmed .shell-tag { color: var(--sh-ink, var(--ink)); }

/* ---------- viewer ---------- */
.canvas-wrap { position: relative; flex: none; }
/* !important on the heights: app.js may set an inline 360px if the canvas is measured while its screen is hidden */
#orbital-canvas {
  position: relative; width: 100%; height: clamp(120px, 28vh, 260px) !important;
  background: var(--viewer-bg); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden;
  touch-action: none;
}
#orbital-canvas canvas { display: block; width: 100% !important; height: 100% !important; }
@media (min-width: 900px) { #orbital-canvas { height: clamp(240px, 46vh, 560px) !important; } }
@media (min-width: 900px) and (max-height: 760px) { #orbital-canvas { height: clamp(220px, 44vh, 560px) !important; } }
#axis-key {
  position: absolute; top: var(--sp-2); left: var(--sp-2); z-index: 2; pointer-events: none;
  font: var(--t-mono); color: var(--ink);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 3px 8px; opacity: .92;
}
.viewer-hint { margin: 0; color: var(--muted); font-size: 1rem; line-height: 1.4; }
.viewer-fallback { padding: var(--sp-4); color: var(--muted); }

.scale-readout { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-5); padding-top: var(--sp-2); border-top: 1px solid var(--line); }
.scale-row { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font: var(--t-small); color: var(--ink); max-width: none; }
.scale-name { font: var(--t-label); letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--muted); }
.scale-value { font: var(--t-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.scale-note { color: var(--muted); }
.scale-more { flex: 1 1 100%; }
.scale-more p { margin: 0 0 var(--sp-2); font-size: 1rem; line-height: 1.5; color: var(--ink); }

/* collapsed-by-default extra information (native <details>: no script needed) */
details.more > summary {
  display: flex; align-items: center; gap: var(--sp-2); min-height: 32px; padding: 2px 0;
  font: var(--t-body-strong); color: var(--link); cursor: pointer; list-style: none; border-radius: var(--r-sm);
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before {
  content: "\25B8"; font-size: .9em; transition: transform var(--dur-fast) var(--ease);
}
details.more[open] > summary::before { transform: rotate(90deg); }
details.more > summary:hover { text-decoration: underline; text-underline-offset: 3px; }
@media (pointer: coarse) { details.more > summary { min-height: var(--control-h); } }

/* ---------- legend (drawn orbitals, one chip per orbital) ---------- */
#viewer-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.legend-title { flex: 1 1 100%; margin: 0; font: var(--t-label); letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--muted); max-width: none; }
.legend-item {
  display: inline-flex; align-items: center; gap: var(--sp-2); padding: 4px 12px; min-height: 34px;
  border-radius: var(--r-pill); font: var(--t-small); color: var(--ink);
  border: 2px solid var(--sh, var(--primary)); background: var(--sh-soft, var(--primary-soft));
}
.legend-chips { display: inline-flex; gap: 3px; }
.legend-chip {
  display: inline-block; width: 14px; height: 14px; border-radius: 4px; flex: none;
  border: 1px solid var(--ink);
}
.legend-name { font-family: var(--font-display); font-weight: var(--w-display); }
.legend-state { font: var(--t-small); color: var(--muted); }
button.legend-item { font-family: inherit; cursor: pointer; transition: background var(--dur-fast, .15s) var(--ease, ease), box-shadow var(--dur-fast, .15s) var(--ease, ease); }
button.legend-item:hover { box-shadow: var(--shadow-1), inset 0 0 0 1px var(--sh, var(--primary)); }
button.legend-item:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; box-shadow: var(--focus-ring); }
.legend-item.is-hidden { border-style: dotted; border-color: var(--muted); background: transparent; color: var(--muted); }
.legend-item.is-hidden .legend-name { text-decoration: line-through; }
.legend-item.is-hidden .legend-chip { opacity: .3; }
.legend-empty { flex: 1 1 100%; margin: 0; font: var(--t-small); color: var(--muted); max-width: none; }
.legend-item.is-solid .legend-chip { opacity: 1; }
.legend-item.is-ghost { border-style: dashed; background: transparent; }
.legend-item.is-ghost .legend-chip {   /* hatched so ghost reads without colour */
  opacity: .6; background-image: repeating-linear-gradient(45deg, transparent 0 3px, var(--card) 3px 5px);
}
.legend-sign { flex: 1 1 100%; margin: 4px 0 0; font: var(--t-small); color: var(--ink); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; max-width: none; }
.legend-sign .legend-chip { border-radius: 50%; }

/* ---------- 2 · quantum numbers ---------- */
.selection-title {
  font-family: var(--font-display); font-weight: var(--w-display); font-size: 1.5rem; line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading); margin: 0 0 var(--sp-3); color: var(--ink);
  min-height: 2.1rem; overflow-wrap: anywhere;
}
.title-focus { display: block; font: var(--t-body); font-size: 1rem; font-weight: var(--w-normal); color: var(--muted); }
.selection-title[data-shell] {
  color: var(--sh-ink); padding: 2px 0 2px var(--sp-3); border-left: 5px solid var(--sh);
}

#qn-panel { margin: 0 0 var(--sp-4); background: var(--card-2); border-radius: var(--r-md); padding: 4px var(--sp-4); }
/* an invisible table: symbol | quantum number | label | tooltip. One row per value; the symbol and the tooltip sit on a group's first row. */
.qn-row {
  display: grid; grid-template-columns: 5.5rem 3rem minmax(0, 1fr) auto; align-items: center; column-gap: var(--sp-2);
}
.qn-row.qn-first { border-top: 1px solid var(--line-strong); }
.qn-row.qn-first:first-child { border-top: 0; }
.qn-key, .qn-val, .qn-label, .qn-end { padding: 5px 0; }
.qn-key { display: flex; align-items: center; flex-wrap: wrap; gap: 0 var(--sp-2); color: var(--ink); }
.qn-sym { font-family: var(--font-display); font-style: italic; font-weight: var(--w-display); font-size: 1.25rem; line-height: 1.2; min-width: 1.4em; }
.qn-name { font: var(--t-small); font-style: normal; color: var(--muted); }
.qn-val { font: var(--t-quantity); font-size: 1.125rem; font-variant-numeric: tabular-nums; font-weight: var(--w-semi); color: var(--ink); }
.qn-label { font: var(--t-quantity); font-size: 1rem; color: var(--ink); overflow-wrap: anywhere; }
.qn-end { justify-self: end; }
.qn-val[data-shell] {
  justify-self: start; padding: 2px 14px; margin: 4px 0; border-radius: var(--r-pill);
  background: var(--sh-soft); color: var(--sh-ink); box-shadow: inset 0 0 0 2px var(--sh);
}
.qn-hint { margin: 0 0 var(--sp-3); font: var(--t-small); color: var(--muted); }
.qn-hint[hidden] { display: none; }
.ms-note { display: block; font: var(--t-small); color: var(--muted); }

/* the old bullet list is gone: its text now lives in the tooltips */
#qn-rules { margin: 0 0 var(--sp-4); padding-left: 1.2em; color: var(--ink); }
#qn-rules:empty { display: none; }
#qn-rules li { margin-bottom: 6px; }
#qn-rules li::marker { color: var(--primary); }

/* real-atom summary (#config-panel is [hidden] in Explore mode):
   name + symbol chip, "Z = 26 · 26 electrons", full / shorthand configuration, ground-state note */
#config-panel { border-top: 1px solid var(--line); padding-top: var(--sp-3); margin-top: var(--sp-1); }
.element-summary { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.element-title { display: flex; align-items: center; flex-wrap: wrap; gap: 2px var(--sp-3); margin: 0; color: var(--ink); }
.element-name { font: var(--w-display) 1.375rem/1.2 var(--font-display); letter-spacing: var(--tr-heading); color: var(--ink); }
.element-symbol {
  display: inline-flex; align-items: center; padding: 1px var(--sp-3); border-radius: var(--r-pill);
  font: var(--w-semi) 1rem/1.4 var(--font-mono);
  color: var(--primary-soft-ink); background: var(--primary-soft); box-shadow: inset 0 0 0 1px var(--primary);
}
.element-symbol:empty, .element-name:empty { display: none; }
#electron-count:empty, #config-notation:empty, #config-status:empty { display: none; }
#electron-count { margin: 0; max-width: none; font: var(--t-quantity); font-weight: var(--w-semi); font-size: .9375rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
#config-notation {
  display: flex; flex-direction: column; gap: 2px; margin: 0; color: var(--ink); background: var(--card-2);
  border-radius: var(--r-md); padding: var(--sp-2) var(--sp-3); overflow-wrap: anywhere; max-width: none;
}
.config-line { display: grid; grid-template-columns: 5.25rem minmax(0, 1fr); align-items: baseline; gap: 0 var(--sp-2); margin: 0; max-width: none; line-height: 1.4; }
.config-key { font: var(--t-label); letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--muted); }
.config-val { font: var(--t-quantity); font-size: 1rem; font-weight: var(--w-semi); font-variant-numeric: tabular-nums; color: var(--ink); overflow-wrap: anywhere; }
.valence-note { margin: 0; max-width: none; font: var(--t-small); color: var(--muted); }
.valence-note:empty, .valence-note[hidden] { display: none; }
#config-status { display: flex; flex-direction: column; gap: 6px; }
.status-line { margin: 0; padding: 6px 12px; font: var(--t-small); line-height: 1.45; border-radius: 0 var(--r-md) var(--r-md) 0; border-left: 3px solid var(--primary); background: var(--primary-soft); color: var(--ink); max-width: none; }
.status-line.is-ok { background: var(--accent-soft); border-left-color: var(--accent); color: var(--accent-soft-ink); }
.status-line.is-warn { background: var(--warn-soft); border-left-color: var(--warn); color: var(--warn-ink); }
.status-line.is-error { background: var(--danger-soft); border-left-color: var(--danger); color: var(--danger); }
.config-shorthand { color: var(--muted); }
#config-status .status-ok, .status-ok {
  background: var(--accent-soft); border-left: 3px solid var(--accent); color: var(--accent-soft-ink); border-radius: 0 var(--r-md) var(--r-md) 0;
}
#config-status .status-warn, .status-warn {
  background: var(--warn-soft); border-left: 3px solid var(--warn); color: var(--warn-ink); border-radius: 0 var(--r-md) var(--r-md) 0;
}
#config-status .status-error, .status-error, .status-danger {
  background: var(--danger-soft); border-left: 3px solid var(--danger); color: var(--danger); border-radius: 0 var(--r-md) var(--r-md) 0;
}
#config-status > .status-ok, #config-status > .status-warn, #config-status > .status-error { padding: 8px 12px; margin: 4px 0; }
#config-status ul { margin: 6px 0 0; padding-left: 1.2em; }

#simplifications { margin-top: var(--sp-4); padding-top: var(--sp-2); border-top: 1px solid var(--line); }
#simplifications ul { margin: var(--sp-2) 0 0; padding-left: 1.2em; }
#simplifications li { margin-bottom: 6px; max-width: none; }
#simplifications li::marker { color: var(--primary); }

/* =============================================================
   START SCREEN  -  two equal choices, centred, calm
   #screen-start > .start-inner > eyebrow, h1, lead, .mode-cards > 2 x button.mode-card
   Both cards carry the same weight (a card surface, a coloured top edge, a small glyph drawn in CSS).
   No card is saturated at rest; the one saturated element is the arrow chip of the card that is hovered
   or focused. The choice is also shown by words and shapes, not by colour alone.
   ============================================================= */
.screen--start {
  display: grid; place-items: center;
  min-height: min(70dvh, 680px);
  padding: var(--sp-6) var(--pad-x) var(--sp-7);
}
.start-inner { width: min(100%, 900px); display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp-2); }
.screen--start .screen-title { margin: 0; font: var(--t-display); letter-spacing: var(--tr-display); color: var(--title); }
.screen-lead { margin: 0 0 var(--sp-5); max-width: none; font: var(--w-normal) 1.1875rem/1.5 var(--font-body); color: var(--muted); }

.mode-cards { width: 100%; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); }
.mode-card {
  --wash: var(--card);             /* both cards sit on the plain card surface: equal weight */
  --tile: var(--primary-soft);
  align-items: center; justify-content: center; text-align: center; gap: var(--sp-3);
  min-height: clamp(250px, 38dvh, 340px); padding: var(--sp-6) var(--sp-5) var(--sp-5);
  border-left: 1px solid var(--line-strong); border-top: 4px solid var(--edge);
  font-family: var(--font-body);
}
.mode-card.choice-card--grn { --tile: var(--accent-soft); }
.mode-card .choice-verb { font: var(--w-display) 1.625rem/1.2 var(--font-display); letter-spacing: var(--tr-heading); }
.mode-card .choice-desc { max-width: 30ch; font: var(--w-normal) 1.0625rem/1.5 var(--font-body); color: var(--ink); }

/* glyph (the ::before): what you will see, drawn from gradients and text only */
.mode-card::before {
  content: ""; flex: none; display: flex; align-items: center; justify-content: center;
  width: 92px; height: 92px; border-radius: var(--r-lg);
  background-color: var(--tile); box-shadow: inset 0 0 0 1px var(--edge);
}
/* Explore orbitals: a p orbital, the two lobes in the viewer's own + / - colours */
.mode-card[data-mode="explore"]::before {
  background:
    radial-gradient(ellipse 17% 20% at 50% 30%, var(--orbital-pos) 0 96%, transparent 100%),
    radial-gradient(ellipse 17% 20% at 50% 70%, var(--orbital-neg) 0 96%, transparent 100%),
    linear-gradient(var(--edge), var(--edge)) 50% 50% / 62% 2px no-repeat,
    var(--tile);
}
/* Real atoms: an element tile. The text is decorative, so it carries empty alt text where supported */
.mode-card[data-mode="atom"]::before {
  content: "Fe"; content: "Fe" / "";
  font: var(--w-display) 2.125rem/1 var(--font-display); color: var(--wash-ink, var(--accent-soft-ink)); letter-spacing: 0;
}
/* the arrow chip (the ::after): says "this goes somewhere" */
.mode-card::after {
  content: "\2192"; content: "\2192" / "";
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 56px; height: 34px; margin-top: var(--sp-1); border-radius: var(--r-pill);
  font: var(--w-semi) 1.25rem/1 var(--font-body); color: var(--wash-ink); background: var(--tile); box-shadow: inset 0 0 0 1px var(--edge);
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.mode-card:hover::after, .mode-card:focus-visible::after { background: var(--primary); color: var(--primary-ink); box-shadow: none; transform: translateX(2px); }
.mode-card.choice-card--grn:hover::after, .mode-card.choice-card--grn:focus-visible::after { background: var(--accent); color: var(--accent-ink); }
.mode-card:focus-visible { outline: 3px solid var(--primary); outline-offset: 3px; }

/* =============================================================
   TABLE SCREEN  -  a wide card titled "Periodic table selector"
   #screen-table > .table-card > .table-card__head h1 | #table-mount | .table-card__foot (#table-back + #table-hint)
   The grid is periodic-table.js (.pt-*). Cells are SQUARES whose size comes from the width of #table-mount
   (and the screen height), so 18 columns fit ~1100 wide at 1280x800 (cells ~58px) and shrink with the screen.
   ============================================================= */
.screen--table {
  display: grid; place-items: center;
  min-height: min(70dvh, 680px);
  padding: var(--sp-5) var(--pad-x);
}
.table-card { width: min(100%, 1180px); display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); }
@media (min-width: 1600px) { .table-card { width: min(100%, 1300px); } }   /* big screens: cells grow up to 64px */
.table-card__head { margin: 0; min-height: 0; }
.table-card .screen-title { margin: 0; font: var(--w-display) 1.625rem/1.25 var(--font-display); letter-spacing: var(--tr-heading); color: var(--ink); }
.table-card__foot { display: flex; align-items: center; gap: var(--sp-4); }
.table-card__foot .btn { flex: none; }
.table-hint {
  flex: 1 1 auto; min-width: 0; margin: 0; max-width: none; min-height: 40px; padding: 6px var(--sp-4);
  display: flex; align-items: center;
  font: var(--t-quantity); font-size: .9375rem; color: var(--ink);
  background: var(--bg-tint); border: 1px solid var(--line); border-radius: var(--r-md);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

#table-mount {
  container-type: inline-size;
  --pt-gap: 3px; --pt-label-w: 1.75rem; --pt-min-width: 0px;
  --pt-cell: clamp(30px, min(calc((100cqw - var(--pt-label-w) - 17 * var(--pt-gap) - 12px) / 18), calc((100vh - 330px) / 5.3), calc((100dvh - 330px) / 5.3)), 64px);
}
.pt { padding: 4px; overflow-x: auto; scrollbar-width: thin; }
.pt-table {
  width: max-content; min-width: 0; margin-inline: auto; gap: var(--pt-gap);
  grid-template-columns: var(--pt-label-w) repeat(18, var(--pt-cell));
  grid-template-rows: auto repeat(5, var(--pt-cell));
}
.pt-colhead, .pt-rowhead { font: var(--t-label); font-variant-numeric: tabular-nums; color: var(--muted); }
.pt-colhead { align-items: flex-end; padding-bottom: 2px; }

.pt-cell[data-block="s"], .pt-key-swatch[data-block="s"] { --b: var(--blk-s); --b-soft: var(--blk-s-soft); --b-ink: var(--blk-s-ink); }
.pt-cell[data-block="p"], .pt-key-swatch[data-block="p"] { --b: var(--blk-p); --b-soft: var(--blk-p-soft); --b-ink: var(--blk-p-ink); }
.pt-cell[data-block="d"], .pt-key-swatch[data-block="d"] { --b: var(--blk-d); --b-soft: var(--blk-d-soft); --b-ink: var(--blk-d-ink); }

.pt-cell {
  min-height: 0; border-radius: 8px; cursor: pointer; font-family: var(--font-body);
  color: var(--b-ink, var(--ink)); background: var(--b-soft, var(--card)); border: 1px solid var(--b, var(--line-strong));
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.pt-cell:hover { transform: translateY(-1px); border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary), var(--shadow-1); z-index: 1; }
.pt-sym { font: var(--w-semi) clamp(.8125rem, calc(var(--pt-cell) * .36), 1.375rem)/1.1 var(--font-display); }
.pt-num { position: absolute; top: 3px; left: 4px; font: var(--w-medium) clamp(.625rem, calc(var(--pt-cell) * .2), .8125rem)/1 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.pt-block { left: 5px; bottom: 3px; font: italic var(--w-semi) clamp(.625rem, calc(var(--pt-cell) * .2), .8125rem)/1 var(--font-mono); color: var(--b-ink, var(--ink-2)); }
.pt-flag { top: 2px; right: 4px; font-size: clamp(.625rem, calc(var(--pt-cell) * .2), .8125rem); color: var(--warn-ink); }

/* selected: inverted fill + a ring in the card colour and the primary + a check mark. Never colour alone. */
.pt-cell.is-selected, .pt-cell[aria-pressed="true"] {
  color: var(--primary-ink); background: var(--primary); border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--primary); z-index: 2;
}
.pt-cell.is-selected :is(.pt-num, .pt-block, .pt-flag), .pt-cell[aria-pressed="true"] :is(.pt-num, .pt-block, .pt-flag) { color: inherit; }
.pt-cell.is-selected::after, .pt-cell[aria-pressed="true"]::after {
  content: "\2713"; position: absolute; right: 4px; bottom: 2px; font: var(--w-bold) clamp(.625rem, calc(var(--pt-cell) * .22), .875rem)/1 var(--font-body);
}
.pt-cell.is-selected:focus-visible, .pt-cell[aria-pressed="true"]:focus-visible { outline-offset: 5px; }

/* legend */
.pt-legend { margin: var(--sp-3) 0 0; align-items: center; gap: var(--sp-1) var(--sp-5); }
.pt-legend li { font: var(--t-small); max-width: none; color: var(--ink); }
.pt-key-swatch { inline-size: 24px; block-size: 24px; color: var(--b-ink); background: var(--b-soft); border: 1px solid var(--b); }
.pt-key-swatch .pt-block { position: static; font: italic var(--w-bold) .8125rem/1 var(--font-mono); }
.pt-key .pt-flag { position: static; font-size: 1rem; color: var(--warn-ink); }
.pt-key-axes { margin-left: auto; color: var(--muted); }
@media (max-width: 760px) { .pt-key-axes { display: none; } }

/* ---------- tooltips (info button + popover), markup built by app.js ----------
   <span class="tip-wrap"><button class="info-tip">i</button><span class="tip-pop" role="tooltip" hidden>..</span></span>
   Hidden until app.js removes [hidden]. app.js may add a placement modifier to .tip-pop:
     .is-above  open upwards instead of downwards
     .is-left   popover extends LEFTWARDS (its right edge lines up with the button)
     .is-right  popover extends RIGHTWARDS (its left edge lines up with the button)
   With no modifier it opens below, centred on the button. */
.tip-wrap { position: relative; display: inline-flex; align-items: center; vertical-align: middle; flex: none; }
.info-tip {
  position: relative; flex: none; width: 24px; height: 24px; padding: 0; margin: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--primary); border-radius: 50%;
  background: var(--card); color: var(--primary-soft-ink);
  font: italic var(--w-display) .875rem/1 var(--font-display); text-transform: none; letter-spacing: 0; cursor: help;
  transition: background-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.info-tip::after { content: ""; position: absolute; inset: -4px; }                      /* 32px target */
@media (pointer: coarse) { .info-tip::after { inset: -10px; } }                         /* 44px target */
.info-tip:hover { background: var(--primary-soft); }
.info-tip[aria-expanded="true"] { background: var(--primary-soft); box-shadow: inset 0 0 0 1.5px var(--primary); }

.tip-pop {
  --tip-gap: 10px;
  position: absolute; z-index: 60;
  top: calc(100% + var(--tip-gap)); left: 50%; transform: translateX(-50%);
  width: max-content; max-width: min(280px, calc(100vw - 2 * var(--sp-4)));
  padding: var(--sp-3) var(--sp-4);
  color: var(--tip-ink); background: var(--tip-bg);
  border: 1px solid var(--tip-line); border-radius: var(--r-md); box-shadow: var(--shadow-3);
  font: var(--w-normal) 1rem/1.5 var(--font-body); font-style: normal; text-align: left;
  letter-spacing: 0; text-transform: none; white-space: normal; overflow-wrap: break-word;
  animation: tip-in var(--dur-fast) var(--ease);
}
.tip-pop[hidden] { display: none; }
.tip-pop p, .tip-pop li, .tip-pop span, .tip-pop div, .tip-pop em, .tip-pop strong, .tip-pop code, .tip-pop sub, .tip-pop sup {
  color: inherit; font-family: inherit; max-width: none;
}
.tip-pop p, .tip-pop li, .tip-pop div { font-size: 1rem; line-height: 1.5; font-weight: var(--w-normal); font-style: normal; margin: 0; }
.tip-pop p + p, .tip-pop p + ul, .tip-pop ul + p, .tip-pop div + div { margin-top: var(--sp-2); }
.tip-pop ul { margin: var(--sp-1) 0 0; padding-left: 1.1em; }
.tip-pop strong { font-weight: var(--w-semi); }
.tip-pop code { font-family: var(--font-mono); font-size: .95em; }
.tip-pop::before {                 /* arrow */
  content: ""; position: absolute; top: -6px; left: 50%; width: 10px; height: 10px; margin-left: -5px;
  background: var(--tip-bg); border-top: 1px solid var(--tip-line); border-left: 1px solid var(--tip-line);
  transform: rotate(45deg);
}
.tip-pop::after {                  /* invisible bridge so the pointer can travel from button to popover */
  content: ""; position: absolute; left: 0; right: 0; top: calc(-1 * var(--tip-gap)); height: var(--tip-gap);
}
.tip-pop.is-above { top: auto; bottom: calc(100% + var(--tip-gap)); }
.tip-pop.is-above::before { top: auto; bottom: -6px; transform: rotate(225deg); }
.tip-pop.is-above::after { top: auto; bottom: calc(-1 * var(--tip-gap)); }
.tip-pop.is-left  { left: auto; right: -6px; transform: none; }
.tip-pop.is-left::before  { left: auto; right: 13px; margin-left: 0; }
.tip-pop.is-right { left: -6px; right: auto; transform: none; }
.tip-pop.is-right::before { left: 13px; margin-left: 0; }
@keyframes tip-in { from { opacity: 0; } to { opacity: 1; } }

/* tips sit inline next to their label */
.qn-end .tip-wrap, .energy-axis .tip-wrap { margin-left: 2px; }

/* ---------- compact boxes on narrow phones so rows never overflow at 360px ---------- */
@media (max-width: 480px) {
  :root { --box: 44px; }
  #energy-diagram { --axis-pad: 32px; --arrow-fs: 1.3rem; }
  .subshell-row { padding-left: 8px; padding-right: 4px; }
  .shell-tag { min-width: 46px; }
  .app-bar { gap: var(--sp-1) var(--sp-3); }
  .app-bar .top-links, .app-bar__title { display: none; }   /* the logo alone is enough on a phone */
  .mode-cards { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .mode-card { min-height: 0; padding: var(--sp-5) var(--sp-4) var(--sp-4); }
  .table-card { padding: var(--sp-4); }
}
@media (max-width: 899px) {
  .app-bar__title { display: none; }               /* the logo alone keeps the bar on one line on a tablet in portrait */
}
@media (max-width: 640px) {
  /* app bar on a phone: logo + theme toggle on the first line, mode switch + element chip on the second */
  .app-bar__brand { flex: 1 1 auto; }
  .app-bar .theme-toggle { order: 2; }
  .app-bar__tools { order: 3; flex: 1 1 100%; margin-left: 0; }
  .mode-switch .seg > label { padding: 4px var(--sp-3); }
  .element-chip__change { font-size: 0; padding: 3px var(--sp-2); }          /* just the chevron; the chip still says "change" to assistive tech */
  .element-chip__change::after { font-size: .875rem; }
}
@media (max-width: 760px) {
  .mode-cards { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .mode-card { min-height: 0; }
  .table-card__foot { flex-wrap: wrap; }
  .table-hint { flex-basis: 100%; white-space: normal; }
}

/* a short, wide phone (landscape): keep the docked viewer small */
@media (max-width: 899px) and (max-height: 520px) {
  #orbital-canvas { height: clamp(110px, 38vh, 220px) !important; }
}

/* =============================================================
   FIT LAYOUT  -  the whole app view with NO page scroll
   Landscape screens from 1000 x 700 up (1280x720, 1280x800, 1366x768, 1440x900, 1920x1080, a landscape
   tablet). The page is exactly one viewport tall; the app bar is slim, the three cards share the rest, and
   the energy diagram sizes its 11 rows from the room it really has:
       --box = (diagram height - axis row - gaps) / 11  -  row padding  -  m_l tag
   Box, labels, arrows, tags and selection rings all scale from that one number. Nothing is clipped, and
   nothing scrolls, in the diagram. Narrower or portrait screens keep the scrolling layout above (with the
   docked / sticky viewer).
   ============================================================= */
@media (min-width: 1000px) and (min-height: 700px) and (min-aspect-ratio: 6/5) {
  :root { --bar-h: 48px; --row-gap: 2px; --axis-h: 20px; --ml-h: 12px; --fit-gap: 12px; }

  body { height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
  .app-bar { padding-block: 4px; }
  .app-main { flex: 1 1 0; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  .site-footer { display: none; }
  .screen { height: 100%; }
  .screen--start, .screen--table { min-height: 0; }
  .screen--start { padding-block: var(--sp-5); }
  .screen--table { padding-block: var(--sp-4); }

  /* --- the three cards --- */
  #screen-app {
    display: grid; align-items: stretch; gap: var(--fit-gap);
    grid-template-columns: minmax(0, 1.3fr) minmax(0, .8fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "diagram info viewer";
    max-width: 1760px; padding: 6px var(--pad-x) 12px;
  }
  #screen-app > .card { padding: 10px 14px; min-height: 0; box-shadow: var(--shadow-2); }
  .card-head { min-height: 32px; margin-bottom: 6px; gap: var(--sp-2); }
  .card-title { font: var(--w-display) 1.125rem/1.25 var(--font-display); }
  .step { width: 24px; height: 24px; font-size: .75rem; }
  .card-head .btn { min-height: 30px; padding: 2px 14px; font-size: .9375rem; }

  /* --- 1 · energy diagram: title + "Select by" on one line, hint under it, the 11 rows fill the rest --- */
  #panel-diagram {
    display: grid; column-gap: var(--sp-3);
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto auto minmax(0, 1fr);
    grid-template-areas: "head head" "seg seg" "hint hint" "diagram diagram";
  }
  #panel-diagram > .card-head { grid-area: head; }
  .slice-bar { display: contents; }
  #slice-mode { grid-area: seg; }
  #slice-mode legend {   /* still names the group for screen readers; the segments say the rest */
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  #slice-mode .seg { --control-h: 38px; flex-wrap: nowrap; }
  #slice-mode .seg > label { padding: 2px 14px; font-size: .9375rem; }
  .slice-hint { grid-area: hint; max-width: none; margin: 4px 0 6px; font-size: .8125rem; line-height: 1.3; }
  #energy-diagram { grid-area: diagram; min-height: 0; }

  /* --- sizes: fallback from the viewport height, then the exact version from the diagram's own size --- */
  #energy-diagram {
    --axis-pad: 32px; --row-pad: 3px; --ring-gap: 1px; --ring-w: 2px; --sel-bw: 3px; --badge: 14px;
    --ml-fs: .6875rem;
    --box: clamp(28px, calc((100dvh - 340px) / 11 - 2 * var(--row-pad) - var(--ml-h) - var(--row-gap)), 64px);
    --box-w: clamp(30px, calc(var(--box) * 1.15), 72px);
    --name-zone: clamp(11px, calc(var(--box) * .34), 16px);
    --name-fs: clamp(.625rem, calc(var(--box) * .3), .8125rem);
    --arrow-fs: clamp(.9375rem, calc((var(--box) - var(--name-zone)) * .95), 1.9rem);
  }
  @supports (width: 1cqw) {
    #energy-diagram {
      container-type: size;
      --box: clamp(28px, calc((100cqh - var(--axis-h) - var(--sp-1) - 11 * var(--row-gap)) / 11 - 2 * var(--row-pad) - var(--ml-h)), 64px);
      --box-w: clamp(30px, min(calc(var(--box) * 1.15), calc((100cqw - 150px) / 5)), 72px);
    }
  }
  .subshell-row { flex-wrap: nowrap; gap: 6px; padding-right: 6px; }
  .orbital-boxes { flex-wrap: nowrap; gap: 5px; }
  .subshell-label { min-width: 38px; padding: 0 6px; }
  .shell-tag { min-width: 44px; padding: 0 6px; }
  .energy-axis { flex-wrap: nowrap; }
  .orbital-box:hover { transform: none; }          /* a lift would collide with the next row at this density */

  /* --- 2 · quantum numbers + real-atom summary: a column; if everything is opened at once, the summary
         and the "simplifies" list scroll inside the card (the tooltips on the rows above are never clipped) --- */
  #panel-info { display: flex; flex-direction: column; }
  #panel-info > * { flex: none; }
  #panel-info > #config-panel { flex: 0 1 auto; }
  .selection-title { margin: 0 0 var(--sp-2); font-size: 1.25rem; min-height: 0; }
  #qn-panel { margin: 0 0 var(--sp-2); padding: 0 var(--sp-3); }
  .qn-row { grid-template-columns: 5.25rem 2.75rem minmax(0, 1fr) auto; column-gap: var(--sp-1); }
  .qn-key, .qn-val, .qn-label, .qn-end { padding: 2px 0; }
  .qn-sym { font-size: 1.125rem; }
  .qn-val, .qn-label { font-size: 1.0625rem; }
  .qn-val[data-shell] { margin: 2px 0; padding: 1px 10px; }
  .qn-hint { margin: 0 0 var(--sp-2); }
  #qn-rules { margin: 0 0 var(--sp-2); }
  #config-panel { min-height: 9rem; overflow-y: auto; scrollbar-width: thin; padding-top: var(--sp-2); }   /* last resort for a very long note */
  #config-panel[hidden] { display: none; }
  #simplifications { margin-top: var(--sp-2); padding-top: var(--sp-1); }
  #simplifications[open] { flex: 0 1 auto; min-height: 0; max-height: 45%; overflow-y: auto; scrollbar-width: thin; }
  details.more > summary { min-height: 28px; }

  /* --- 3 · viewer: the canvas takes whatever height is left --- */
  #panel-viewer { position: static; align-self: stretch; max-height: none; overflow: hidden; gap: 6px; box-shadow: var(--shadow-2); }
  #panel-viewer .card-head { margin: 0; }
  #panel-viewer { container-type: inline-size; }
  /* the 3-D scene is framed by height, so a very tall, narrow canvas would crop its sides: cap the height at 1.3 x the width */
  .canvas-wrap { flex: 1 1 0; min-height: 120px; max-height: 130cqw; }
  #orbital-canvas { position: absolute; inset: 0; width: auto; height: auto !important; }
  #axis-key { top: var(--sp-1); left: var(--sp-1); padding: 2px 8px; font-size: .75rem; }
  .viewer-hint { font-size: .8125rem; line-height: 1.3; }
  #viewer-legend { flex: none; min-height: 0; max-height: 92px; overflow-y: auto; gap: 4px 6px; }
  .legend-item { min-height: 28px; padding: 1px 10px; }
  .legend-sign { margin: 2px 0 0; }
  .scale-readout { flex: none; padding-top: 6px; gap: 0 var(--sp-4); }
}
/* a touch screen (the tablet app) keeps the compact rows, but gives the buttons a little more to press */
@media (min-width: 1000px) and (min-height: 700px) and (min-aspect-ratio: 6/5) and (pointer: coarse) {
  .card-head .btn { min-height: 38px; }
  details.more > summary { min-height: 36px; }
  .subshell-label, .shell-tag { min-height: 32px; }
}
/* between 700 and 719 high (just under the smallest supported 1280x720) squeeze the rows a little more */
@media (min-width: 1000px) and (min-height: 700px) and (max-height: 719px) and (min-aspect-ratio: 6/5) {
  #energy-diagram { --row-pad: 2px; --ml-h: 11px; }
}
/* a narrow AND short screen (1000-1179 wide, under 780 high): the title and "Select by" need two lines here,
   so trim the rows' padding and fold the one-line hint into a screen-reader-only note to keep boxes >= 28px */
@media (min-width: 1000px) and (max-width: 1179px) and (min-height: 700px) and (max-height: 779px) and (min-aspect-ratio: 6/5) {
  #energy-diagram { --row-pad: 2px; --ml-h: 11px; }
  .slice-hint {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}
/* the title and the "Select by" control share one line once the diagram card is wide enough */
@media (min-width: 1180px) and (min-height: 700px) and (min-aspect-ratio: 6/5) {
  #panel-diagram {
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas: "head seg" "hint hint" "diagram diagram";
  }
  #panel-diagram > .card-head { margin-bottom: 0; }
  #slice-mode { justify-self: end; }
}

/* reduced motion: no eased transitions or scrolling; animations are shortened to .01ms by design-system.css
   (not removed, so animationend still fires for the screen change) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; scroll-behavior: auto !important; }
}
