/* =============================================================
   styles.css — Chemulate Equilibrium: the app shell.

   Holds only what is specific to this app: the no-scroll dashboard grid and its
   breakpoints, the app bar, the dock, the dialog / bottom-sheet pattern, and the
   small controls the design system does not have (range slider, stepper, switch,
   tooltip). Colour, space, radius, type and motion come from design-system.css and
   eq-tokens.css tokens only: no hex, no easing, no UI duration written here.

   Shared shell classes are reused, never redefined: .card .btn .seg .select
   .num-input .choice-card .ds-chip .ds-note .home-link .brand-mark .theme-toggle.
   Where a control's boundary is too faint (design-system's --line-strong is ~1.6:1,
   WCAG 1.4.11 needs 3:1) this file recolours the border with --eq-edge from eq-tokens.css.

   Adapted third-party components (Uiverse.io, MIT licence, as in
   chemulator/uiverse-components.css):
     .eq-switch    from "simple, small, switcher" by @catraco
                   https://uiverse.io/catraco/soft-falcon-9   (MIT, Uiverse)
                   changed: tokens only, 44px target, role=switch, solid focus ring
     .uv-tip       from "tooltip" by @G4b413l
                   https://uiverse.io/G4b413l/dry-turtle-84   (MIT, Uiverse)
                   changed: one shared element placed by JS, solid inverted token pair, hoverable
   The range slider (.eq-range), stepper (.eq-step), gauge and dialog patterns are our
   own, written to research/UI-COMPONENTS.md sections 5 and 6.

   There is no overflow:auto|scroll anywhere in this file. Content that does not fit goes
   into a paginated <dialog> (app.js packs pages to the room that really exists).
   ============================================================= */

html, body { height: 100%; overflow: hidden; }
body { margin: 0; }
strong, b { font-weight: var(--w-semi); }

/* real sub/superscripts that never change the line height (same as the sibling apps) */
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; }
[data-ico] { display: inline-flex; }

/* control boundaries that must reach 3:1 (WCAG 1.4.11): fields, outline buttons, segmented trays */
.select, .num-input, .text-input { border-color: var(--eq-edge); }
.btn:not(.btn--primary):not(.btn--soft):not(.btn--accent) { border-color: var(--eq-edge); }
.seg { border-color: var(--eq-edge); }
/* a control that is unavailable keeps its text colour (4.5:1) and says so with a dashed edge, not with low opacity */
.btn[aria-disabled="true"] { opacity: 1; background: transparent; color: var(--muted); border: 1px dashed var(--eq-edge); cursor: not-allowed; }
.btn[aria-disabled="true"]:hover { background: transparent; border-color: var(--eq-edge); }

/* =============================================================
   1. APP GRID — one viewport tall, nothing scrolls
   ============================================================= */
.app {
  height: 100vh; height: 100dvh; width: 100%; overflow: hidden;
  display: grid; row-gap: var(--sp-2); padding-bottom: var(--sp-1);
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: "bar" "stage" "dock";
}
.app-bar { grid-area: bar; }
.stage {
  grid-area: stage; min-height: 0; min-width: 0; padding-inline: var(--sp-3);
  display: grid; gap: var(--sp-3);
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  grid-template-areas: "left side";
}
.left { grid-area: left; display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: var(--sp-2); min-height: 0; min-width: 0; }
.side { grid-area: side; display: grid; grid-template-rows: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--sp-3); min-height: 0; min-width: 0; }
.dock { grid-area: dock; margin: 0 var(--sp-3) var(--sp-2); min-width: 0; }
.tabs { display: none; grid-area: tabs; }

/* every panel is a size container: its content shrinks, its tracks never grow */
.panel { min-height: 0; min-width: 0; overflow: hidden; display: flex; flex-direction: column; padding: var(--sp-2) var(--sp-3); container-type: size; }
.graph { container-name: graph; }
.saw   { container-name: saw; }
.box   { container-name: box; }
.host  { position: relative; flex: 1 1 0; min-height: 0; min-width: 0; }

/* tablet portrait (820 x 1180): graph on top, see-saw and container side by side below */
@media (max-width: 900px) and (min-height: 521px) {
  .stage { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1.1fr) minmax(0, 1fr); grid-template-areas: "left" "side"; }
  .side { grid-template-rows: minmax(0, 1fr); grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
}


/* phone portrait (390 x 844): ONE panel at a time; the controls live in a bottom sheet.
   Tabs are first in the DOM, so tab order follows what is seen. */
@media (max-width: 600px) and (min-height: 521px) {
  .stage { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; grid-template-areas: "tabs" "view" "trans"; gap: var(--sp-2); }
  .left, .side { display: contents; }
  .graph, .saw, .box { grid-area: view; }
  .transport { grid-area: trans; }
  .tabs { display: inline-flex; width: 100%; }
  .tabs > button { flex: 1 1 0; }
  .app[data-tab="graph"] .saw, .app[data-tab="graph"] .box,
  .app[data-tab="saw"] .graph, .app[data-tab="saw"] .box,
  .app[data-tab="box"] .graph, .app[data-tab="box"] .saw { display: none; }
}

/* short screens (401-520 px high): phone landscape (844 x 390 is the next band down), a laptop at 200 % zoom.
   The chart stays; the see-saw and the container share the right column through tabs;
   the controls move into a dialog opened from the transport row. */
@media (max-height: 520px) and (min-height: 401px) {
  .app { row-gap: var(--sp-1); }
  .stage { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto;
           grid-template-areas: "graph tabs" "graph side" "trans side"; gap: var(--sp-1) var(--sp-2); padding-inline: var(--sp-2); }
  .left, .side { display: contents; }
  .graph { grid-area: graph; }
  .saw, .box { grid-area: side; }
  .transport { grid-area: trans; }
  .tabs { display: inline-flex; }
  .tabs > button[data-tab="graph"] { display: none; }
  .tabs > button { flex: 1 1 0; }
  .app:not([data-tab="box"]) .box { display: none; }
  .app[data-tab="box"] .saw { display: none; }
}

/* very short (400 px or less: 844x390 landscape, 300 % / 400 % zoom): ONE panel at a time, like a phone, so nothing is
   squeezed to a few pixels and nothing hidden stays focusable (hidden panels are display:none). */
@media (max-height: 400px) {
  .app { row-gap: var(--sp-1); }
  .stage { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: minmax(0, 1fr) auto;
           grid-template-areas: "view view" "trans tabs"; gap: var(--sp-1) var(--sp-2); padding-inline: var(--sp-2); }
  .left, .side { display: contents; }
  .graph, .saw, .box { grid-area: view; }
  .transport { grid-area: trans; }
  .tabs { display: inline-flex; }
  .tabs > button { flex: 0 0 auto; }
  .app:not([data-tab="graph"]) .graph, .app:not([data-tab="saw"]) .saw, .app:not([data-tab="box"]) .box { display: none; }
}
@media (max-height: 400px) {
  #btn-jump .tp-btn__txt, #btn-table .tp-btn__txt { display: none; }
  #btn-jump, #btn-table { width: var(--control-h); padding: 0; }
}
@media (max-height: 400px) and (max-width: 560px) {
  .stage { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto auto; grid-template-areas: "view" "trans" "tabs"; }
  .tabs { width: 100%; } .tabs > button { flex: 1 1 0; }
}

/* on phones and short screens the dock lives in the Controls dialog (app.js moves it there) */
@media (max-width: 600px) and (min-height: 521px), (max-height: 520px) {
  .app { grid-template-rows: auto minmax(0, 1fr); grid-template-areas: "bar" "stage"; }
  .app > .dock { display: none; }
}

/* =============================================================
   2. APP BAR  (the sibling apps' pattern: slim, controls one step smaller)
      DOM order is the visual order: home | mark | mode | reaction chip | help | theme
   ============================================================= */
.app-bar {
  position: relative; z-index: 40;
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg); border-bottom: 1px solid var(--line);
  --control-h: 40px;
}
.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; }
.app-bar .theme-toggle { position: static; flex: none; width: 40px; height: 40px; font-size: 1.05rem; box-shadow: none; }
.bar-btn { min-height: var(--control-h); padding: 4px var(--sp-3); font: var(--t-small); font-weight: var(--w-semi); }

/* the reaction chip: the equation, and a chevron that says "this opens a list". Long names end in an ellipsis; the
   full text is in its title and accessible name. */
.rxn-chip {
  display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; max-width: 100%;
  min-height: var(--control-h); padding: 3px 6px 3px var(--sp-4);
  font: var(--t-body-strong); line-height: 1.25; text-align: left;
  color: var(--primary-soft-ink); background: var(--primary-soft);
  border: 1px solid var(--eq-edge); border-radius: var(--r-pill); cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.rxn-chip:hover { border-color: var(--primary); }
.rxn-chip__eq { font-weight: var(--w-bold); color: var(--title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rxn-chip__go { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--card); color: var(--primary-soft-ink); flex: none; }

/* mode switch: soft segmented control, the chosen mode also carries a tick (never colour alone; the tick is not part of the name) */
.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; min-height: calc(var(--control-h) - 8px); }
.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; }

@media (min-width: 701px) { .app-bar__tools { margin-left: auto; } .rxn-chip { flex: 0 1 auto; } }
@media (max-width: 1100px) {
  .app-bar__title { display: none; }
  .rxn-chip { max-width: 38ch; }
}
@media (max-width: 900px) { .bar-btn__txt { display: none; } .bar-btn { width: var(--control-h); padding: 0; } }
/* phone: row 1 = mark + mode, row 2 = chip + help + theme (bar <= 96 px); the order of rows equals the order of the DOM */
@media (max-width: 600px) {
  .app-bar { padding-block: var(--sp-1); }
  .app-bar .top-links { display: none; }
  .app-bar__brand { flex: 1 1 auto; }
  .mode-switch { margin-left: auto; }
  .rxn-chip { flex: 1 1 calc(100% - 104px); max-width: none; }
  .app-bar__tools { display: contents; }
}
@media (max-height: 520px) {
  .app-bar { padding-block: var(--sp-1); padding-inline: var(--sp-2); gap: var(--sp-1) var(--sp-2); flex-wrap: nowrap; }
  .app-bar .top-links, .app-bar__title { display: none; }
  .app-bar__brand { flex: none; }
  .app-bar__brand img { height: 26px; }
  .mode-switch .seg > label { padding-inline: var(--sp-3); font-size: .875rem; }
  .rxn-chip { flex: 0 1 auto; max-width: none; margin-left: 0; }
  .app-bar__tools { display: flex; margin-left: auto; flex-wrap: nowrap; gap: var(--sp-1) var(--sp-2); }
}
@media (max-height: 520px) and (max-width: 600px) {
  .app-bar { flex-wrap: wrap; }
  .rxn-chip { flex: 1 1 calc(100% - 104px); }
  .app-bar__tools { display: contents; }
}

/* =============================================================
   3. TRANSPORT
   ============================================================= */
.transport { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); min-width: 0; padding: 0 var(--sp-1) 4px; }
.tp-btn { padding: 6px var(--sp-4); gap: var(--sp-2); }
.tp-spacer { flex: 1 1 0; min-width: 0; }
.tp-speed > button { padding: 6px 10px; }
.tp-speed-sel { display: none; width: 6.5rem; }
/* Play is the one saturated control in Equilibrium mode; in Le Chatelier mode the just-disturbed balloon is */
.app[data-mode="lc"] #btn-play { background: var(--primary-soft); color: var(--primary-soft-ink); }
.app[data-mode="lc"] #btn-play:hover { background: var(--card-2); }
.btn[data-hint="true"] { box-shadow: 0 0 0 3px var(--primary-soft), 0 0 0 5px var(--primary); }
/* the transport adapts to the room its own column has (the graph column is narrower in Le Chatelier mode) */
.left { container-type: inline-size; container-name: left; }
@container left (max-width: 760px) { #btn-reset .tp-btn__txt { display: none; } #btn-reset { width: var(--control-h); padding: 0; } }
@container left (max-width: 700px) {
  #btn-jump .tp-btn__txt, #btn-table .tp-btn__txt { display: none; }
  #btn-jump, #btn-table { width: var(--control-h); padding: 0; }
}
@container left (max-width: 500px) { .tp-speed { display: none; } .tp-speed-sel { display: inline-block; } }
@media (max-width: 900px) {
  .tp-speed { display: none; }
  .tp-speed-sel { display: inline-block; }
  #btn-reset .tp-btn__txt { display: none; }
  #btn-reset { width: var(--control-h); padding: 0; }
}
@media (max-height: 520px) {
  .transport { gap: var(--sp-1); }
  .tp-btn { padding-inline: var(--sp-3); }
}

/* =============================================================
   4. SEE-SAW CARD FOOT: ONE fixed-height slot (the explanation, or what to do next) and, in Equilibrium
      mode, the two rate bars. The slot never changes height, so showing or hiding an explanation can
      not resize the SVG and rebuild the see-saw in the middle of its own animation.
   ============================================================= */
/* the selected reaction, large, on the see-saw card */
.saw-eq {
  flex: none; margin: 0 0 var(--sp-1); padding: var(--sp-1) var(--sp-3); align-self: center; max-width: 100%;
  font: var(--w-display) clamp(1.25rem, 0.9rem + 1.2vw, 1.75rem)/1.25 var(--font-display);
  letter-spacing: var(--tr-heading); text-align: center; color: var(--title);
  background: var(--primary-soft); border-radius: var(--r-md); overflow-wrap: anywhere;
}
@container (max-height: 300px) { .saw-eq { font-size: 1.125rem; padding: 2px var(--sp-3); } }
@container (max-height: 220px) { .saw-eq { display: none; } }
.saw-thermo {
  flex: none; margin: 0 0 var(--sp-1); padding: 2px var(--sp-3); align-self: center; max-width: 100%;
  font: var(--t-small); font-weight: var(--w-semi); line-height: 1.35; text-align: center;
  color: var(--warn-ink); background: var(--warn-soft); border-radius: var(--r-pill);
}
.saw-thermo[data-kind="flat"] { color: var(--ink-2); background: var(--bg-tint); }
@container (max-height: 260px) { .saw-thermo { display: none; } }
.saw-foot { flex: none; display: grid; gap: var(--sp-1); padding-top: var(--sp-1); }
.slot {
  --slot-h: 5.75rem;
  display: flex; align-items: center; gap: var(--sp-2); height: var(--slot-h); min-width: 0; overflow: hidden;
  padding: var(--sp-1) var(--sp-1) var(--sp-1) var(--sp-3);
  background: var(--primary-soft); border-left: 3px solid var(--primary); border-radius: 0 var(--r-md) var(--r-md) 0;
}
.slot[data-kind="hint"] { background: var(--bg-tint); border-left-color: var(--eq-edge); }
.slot[data-kind="warn"] { background: var(--warn-soft); border-left-color: var(--warn); }
.slot__txt { flex: 1 1 auto; min-width: 0; font: var(--t-small); line-height: 1.4; color: var(--ink); }
.slot__h { display: block; font-weight: var(--w-semi); }
.slot[data-kind="hint"] .slot__txt { color: var(--ink-2); }
.slot__more { flex: none; padding: 6px var(--sp-3); font: var(--t-small); font-weight: var(--w-semi); }
.rates { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
.app[data-mode="lc"] .rates { display: none; }
.rate { display: flex; align-items: center; gap: var(--sp-2); font: var(--t-label); color: var(--muted); min-width: 0; }
.rate__lbl { flex: none; }
.rate__bar { flex: 1 1 auto; min-width: 24px; height: 8px; border-radius: var(--r-pill); background: var(--bg-tint); border: 1px solid var(--eq-edge); overflow: hidden; }
.rate__bar > i { display: block; height: 100%; width: 0; border-radius: var(--r-pill); background: var(--eq-a); }
#rate-r { background: var(--eq-b); }
@container saw (max-height: 420px) { .slot { --slot-h: 4.5rem; } }
@container saw (max-height: 330px) { .slot { --slot-h: 3.5rem; } .rates { display: none; } }
@container saw (max-height: 250px) { .slot { --slot-h: 3.4rem; } }

/* =============================================================
   5. CONTAINER CARD: particle box beside the gauges
   ============================================================= */
.box-cols { flex: 1 1 0; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: var(--sp-3); }
@container box (max-aspect-ratio: 11/10) or (max-width: 440px) {
  .box-cols { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, 1.2fr); }
}

/* =============================================================
   6. DOCK
   ============================================================= */
.dock { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.dock-set { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-2); min-width: 0; flex: 0 1 auto; }
.dock-set[hidden] { display: none; }
.dock-tail { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-2); flex: 0 0 auto; }
.dk-btn { padding: 6px var(--sp-3); font: var(--w-semi) var(--fs-small)/1.3 var(--font-body); }
.dk-sep { width: 1px; height: 28px; background: var(--eq-edge); flex: none; margin-inline: var(--sp-1); }
.dk-qty { display: inline-flex; align-items: center; gap: var(--sp-2); font: var(--t-small); font-weight: var(--w-semi); color: var(--muted); }
.dk-qty .select { font-size: var(--fs-small); padding-block: 6px; }
.dk-temp { display: flex; align-items: center; gap: var(--sp-2); flex: 1 1 280px; min-width: 240px; max-width: 380px; }
.dk-temp__lbl { font: var(--t-small); font-weight: var(--w-semi); color: var(--muted); flex: none; }
.dk-temp__out { font: var(--t-mono); font-variant-numeric: tabular-nums; color: var(--ink); flex: none; min-width: 13ch; text-align: right; }
.dock-reason { flex: 1 1 100%; margin: 0; max-width: none; font: var(--t-small); color: var(--ink); background: var(--warn-soft); border-left: 3px solid var(--warn); border-radius: 0 var(--r-md) var(--r-md) 0; padding: var(--sp-2) var(--sp-3); display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.dock-reason[hidden] { display: none; }
.reason-btn { padding: 4px var(--sp-3); }

/* low-frequency controls: behind "More" on wide screens, inline in the Controls dialog */
.dk-low { display: none; }
.pop .dk-low { display: inline-flex; }
.pop .dk-low[hidden], .dk-low[hidden] { display: none; }
.pop #dk-more { display: none; }
/* narrower than 1100 px the catalyst switch and Reset of the Le Chatelier dock fold into "More" too (one row, never two) */
@media (max-width: 1100px) { .app > .dock .dk-fold { display: none; } }

/* the dock inside the Controls dialog: stacked, full width */
.pop .dock { margin: 0; display: grid; gap: var(--sp-3); }
.pop .dock-set, .pop .dock-tail { gap: var(--sp-2); }
.pop .dk-temp { flex: 1 1 100%; max-width: none; min-width: 0; }
.pop .dk-sep { display: none; }

/* ---- range slider (own; research/UI-COMPONENTS.md 5.2). The thumb ring and the input outline both show focus ---- */
.eq-range { --pct: 50%; -webkit-appearance: none; appearance: none; flex: 1 1 auto; min-width: 80px; width: 100%; height: var(--control-h); margin: 0; background: transparent; cursor: pointer; border-radius: var(--r-sm); }
.eq-range::-webkit-slider-runnable-track { height: 6px; border-radius: var(--r-pill); background: linear-gradient(to right, var(--primary) var(--pct), var(--eq-edge) var(--pct)); }
.eq-range::-moz-range-track { height: 6px; border-radius: var(--r-pill); background: var(--eq-edge); }
.eq-range::-moz-range-progress { height: 6px; border-radius: var(--r-pill); background: var(--primary); }
.eq-range::-webkit-slider-thumb { -webkit-appearance: none; width: 26px; height: 26px; margin-top: -10px; border-radius: 50%; background: var(--card); border: 3px solid var(--primary); box-shadow: var(--shadow-1); }
.eq-range::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: var(--card); border: 3px solid var(--primary); box-shadow: var(--shadow-1); }
.eq-range:hover::-webkit-slider-thumb, .eq-range:hover::-moz-range-thumb { box-shadow: var(--shadow-1), 0 0 0 6px var(--primary-soft); }
.eq-range:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; box-shadow: none; }
.eq-range:focus-visible::-webkit-slider-thumb, .eq-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px var(--card), 0 0 0 5px var(--primary); }
.eq-range:disabled { opacity: .5; cursor: not-allowed; }

/* ---- +/- stepper (own): .btn + .num-input + native stepUp/stepDown ---- */
.eq-step { display: inline-flex; align-items: center; gap: var(--sp-2); flex: none; }
.eq-step .btn { width: var(--control-h); padding: 0; font-size: 1.25rem; flex: none; }
.eq-step .num-input { width: 8.5ch; padding-inline: 6px; text-align: center; -moz-appearance: textfield; appearance: textfield; }
.eq-step .num-input::-webkit-outer-spin-button, .eq-step .num-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- switch (adapted from Uiverse "simple, small, switcher" by @catraco, MIT) ---- */
.eq-switch { position: relative; display: inline-flex; align-items: center; gap: var(--sp-3); min-height: var(--control-h); cursor: pointer; font: var(--w-semi) var(--fs-small)/1.3 var(--font-body); color: var(--ink); }
.eq-switch > input { position: absolute; opacity: 0; width: 54px; height: var(--control-h); margin: 0; cursor: pointer; }
.eq-switch .track { --trk: var(--muted); box-sizing: border-box; flex: none; width: 54px; height: 30px; border-radius: var(--r-pill); background: var(--trk); position: relative; transition: background-color var(--dur) var(--ease); }
.eq-switch .knob { box-sizing: border-box; position: absolute; top: 0; left: 0; width: 30px; height: 30px; border-radius: 50%; border: 4px solid var(--trk); background: var(--card); transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), background-color var(--dur) var(--ease); }
.eq-switch > input:checked + .track { --trk: var(--accent); }
.eq-switch > input:checked + .track .knob { transform: translateX(24px); background: var(--accent-ink); }
.eq-switch > input:focus-visible + .track { outline: 2px solid var(--primary); outline-offset: 3px; box-shadow: none; }
.eq-switch > input:focus-visible { outline: none; box-shadow: none; }
.eq-switch > input:disabled + .track { opacity: .5; }
.eq-switch:has(input:disabled) { cursor: not-allowed; }

/* ---- tooltip (adapted from Uiverse "tooltip" by @G4b413l, MIT). Supplementary only: the same fact is always in the
        control's text, aria-description or a popup. One shared element, placed by app.js, so it can never add to the
        page's scroll width; it is clamped to the window, stays while hovered (WCAG 1.4.13) and closes on Esc. ---- */
.uv-tip {
  position: fixed; z-index: 60; max-width: min(260px, 80vw);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm);
  background: var(--ink-2); color: var(--card); font: var(--t-small); text-align: center;
  box-shadow: var(--shadow-2);
}

/* =============================================================
   7. DIALOGS — native <dialog>; bottom sheet under 600px; NEVER overflow:auto.
      Padding lives on .pop-body so a click on the dialog element itself is a backdrop click.
   ============================================================= */
dialog.pop {
  padding: 0; border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--card); color: var(--ink); box-shadow: var(--shadow-3);
  width: min(92vw, 560px); max-width: none; max-height: min(90dvh, 680px); overflow: hidden;
}
dialog.pop[open] { display: flex; flex-direction: column; }
dialog.pop::backdrop { background: var(--overlay); }
dialog.pop--paged { height: min(90dvh, 620px); }
dialog.pop--wide { width: min(94vw, 720px); }
.pop-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); }
.pop-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.pop-title { font: var(--t-h2); letter-spacing: var(--tr-heading); color: var(--ink-2); margin: 0; }
.pop-close { width: var(--control-h); padding: 0; flex: none; }
.pop-main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.pop-main > * { min-width: 0; }
.pop-pre { flex: none; }
.pop-pre:empty { display: none; }
.pop-pages { flex: 0 1 auto; min-height: 0; overflow: hidden; }
.pop--paged .pop-pages { flex: 1 1 0; }
.pop-page { display: grid; gap: var(--sp-3); align-content: start; }
.pop-page[hidden] { display: none; }
.pop-foot { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.pop-foot[hidden] { display: none; }
.pop-nav { display: flex; align-items: center; gap: var(--sp-2); }
.pop-nav .btn { width: var(--control-h); padding: 0; }
.pop-count { font: var(--t-mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.pop-msg { flex: 1 1 0; min-width: 0; font: var(--t-small); color: var(--warn-ink); }
.pop-msg:empty { display: none; }
.pop-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2); }

@media (max-width: 600px) {
  dialog.pop { margin: 0; inset: auto 0 0 0; width: 100%; max-height: 90dvh; border-radius: var(--r-lg) var(--r-lg) 0 0; border-bottom: 0; }
  dialog.pop--paged { height: 88dvh; }
  .pop-body { padding: var(--sp-4); }
}
@media (max-height: 520px) {
  dialog.pop { max-height: 97dvh; width: min(96vw, 680px); }
  dialog.pop--paged { height: 97dvh; }
  .pop-body { padding: var(--sp-2) var(--sp-4); gap: var(--sp-2); }
  .pop-title { font-size: 1.0625rem; }
}

/* text blocks inside paged dialogs */
.pop-page p, .pop-page li { font: var(--t-body); font-size: var(--fs-small); line-height: 1.55; margin: 0; max-width: none; color: var(--ink); }
.pop-page h3 { font: var(--t-h3); color: var(--ink-2); margin: 0; }
.pop-page .blk { display: grid; gap: var(--sp-1); }
.pop-page .eqn { font-size: var(--fs-body); color: var(--ink); }
.pop-page .calc { font: var(--t-mono); font-variant-numeric: tabular-nums; color: var(--ink); background: var(--bg-tint); border-radius: var(--r-sm); padding: var(--sp-2) var(--sp-3); }
.pop-page ul { margin: 0; padding-left: 1.2em; display: grid; gap: var(--sp-1); }
.myth { font-weight: var(--w-semi); color: var(--ink-2); }
.pop-page .ds-note p { font-size: var(--fs-small); }

/* tables inside dialogs: unit text keeps its case (mol/L is not MOL/L) */
.kt { width: 100%; border-collapse: collapse; font: var(--t-small); }
.kt th, .kt td { padding: 6px var(--sp-2); text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
.kt th { font: var(--t-label); text-transform: none; letter-spacing: 0; color: var(--muted); }
.kt td.num, .kt th.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.kt .src { color: var(--muted); }

/* ---- reaction picker ---- */
.pick-tabs { flex: none; }
.pick-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 600px) { .pick-grid { grid-template-columns: minmax(0, 1fr); } }
.pick-card { padding: var(--sp-2) var(--sp-3); gap: 2px; box-shadow: var(--shadow-1); min-height: var(--control-h); min-width: 0; }
.pick-card:hover { transform: none; box-shadow: var(--shadow-2); }
.pick-card__eq { font: var(--w-semi) var(--fs-body)/1.3 var(--font-body); color: var(--ink); }
.pick-card__name { font: var(--t-small); color: var(--muted); line-height: 1.35; }
.pick-card__badges { display: flex; flex-wrap: wrap; gap: 4px; }
.pick-card .ds-chip { font-size: var(--fs-label); padding: 2px 8px; }
.pick-card[aria-current="true"] { box-shadow: var(--shadow-1), 0 0 0 2px var(--primary); }
.pick-card[aria-current="true"]::after { content: "current"; position: absolute; top: 6px; right: 10px; font: var(--t-label); color: var(--primary-soft-ink); }

/* ---- forms in dialogs: amounts, add/remove, heat/cool, inert gas, more ---- */
.rows { display: grid; gap: var(--sp-2); }
.rows--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--sp-4); }
.rows--2 .eq-step { gap: var(--sp-1); }
.rows--2 .row__unit { display: none; }
@media (max-width: 600px) { .rows--2 { grid-template-columns: minmax(0, 1fr); } }
.row { display: grid; grid-template-columns: minmax(0, 1fr) auto 3ch; align-items: center; gap: var(--sp-3); min-width: 0; }
.rows--2 .row { grid-template-columns: minmax(0, 1fr) auto; }
.inert-note { min-height: 9rem; }
.row__lbl { display: flex; flex-direction: column; min-width: 0; font: var(--w-semi) var(--fs-body)/1.25 var(--font-body); }
.row__lbl small { font: var(--t-small); color: var(--muted); }
.row__unit { font: var(--t-mono); color: var(--muted); }
.field-note { margin: 0; max-width: none; font: var(--t-small); color: var(--muted); }
.pop-main .ds-note { margin: 0; max-width: none; font: var(--t-small); line-height: 1.5; }
.pop-main .ds-note strong { font-weight: var(--w-semi); }
.pop-main .form-error { margin: 0; font-size: var(--fs-small); }
.kchg { font: var(--t-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.more-list { display: grid; gap: var(--sp-3); }
.more-list .btn, .more-list .eq-switch { justify-self: start; }

/* ---- Test yourself ---- */
.q-score { font: var(--t-small); color: var(--muted); }
.q-vals { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-2); }
.q-val { display: flex; flex-direction: column; gap: 2px; padding: var(--sp-2) var(--sp-3); background: var(--bg-tint); border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.q-val__n { font: var(--t-label); text-transform: uppercase; letter-spacing: var(--tr-label); color: var(--muted); }
.q-val__v { font: var(--t-quantity); font-variant-numeric: tabular-nums; color: var(--ink); }
.q-val--k { border-color: var(--primary); }
.q-ask { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.q-ask .num-input { width: 14ch; }
.q-ask label { font: var(--t-small); font-weight: var(--w-semi); color: var(--ink-2); }
.q-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); }
@media (max-width: 600px) { .q-opts { grid-template-columns: minmax(0, 1fr); } }
.q-opts .btn { padding: 6px var(--sp-3); font: var(--w-semi) var(--fs-small)/1.3 var(--font-body); text-align: center; }
.q-fb { display: grid; gap: var(--sp-2); }
.q-fb .ds-note { margin: 0; max-width: none; }
[tabindex="-1"]:focus-visible { outline-offset: 2px; }
.mini { width: 100%; height: clamp(80px, 22dvh, 130px); display: block; }
.mini .ax { stroke: var(--eq-edge); stroke-width: 1; fill: none; }
.mini .ln { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; }
.mini .at { stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.mini text { font: var(--w-semi) 11px var(--font-mono); fill: var(--muted); }
.mini-key { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); font: var(--t-label); color: var(--muted); }
.mini-key span { display: inline-flex; align-items: center; gap: 6px; }
.mini-key svg { width: 26px; height: 8px; }
.mini-key line { stroke-width: 2.5; }

@media (prefers-reduced-motion: reduce) {
  .eq-switch .track, .eq-switch .knob { transition: none !important; }
}

/* ---- fix pass 2 ---- */
.dock-reason { max-width: 100%; min-width: 0; overflow-wrap: anywhere; }
.pop-page { min-width: 0; }
.pop-page.ctl-flow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.ctl-flow .dk-temp { flex: 1 1 100%; max-width: none; min-width: 0; flex-wrap: wrap; }
.ctl-flow .dock-reason { flex: 1 1 100%; }
.pop-page .calc, .calc { white-space: normal; overflow-wrap: anywhere; }
.dk-temp__out { min-width: 0; flex: 0 1 auto; }
@media (max-width: 600px) {
  .rxn-chip__eq { white-space: normal; font-size: var(--fs-small); line-height: 1.2; }
  .rxn-chip { padding-block: 2px; }
}
@media (max-height: 520px) {
  .rxn-chip { flex: 1 1 0; min-width: 0; }
  .app-bar__tools { flex: none; }
}
@media (max-height: 520px) and (max-width: 600px) { .rxn-chip { flex: 1 1 calc(100% - 104px); } }

/* =============================================================
   Le Chatelier mode (laptop and tablet): the see-saw alone fills the work area; the graph and the container
   are toggled on from the transport row and take their own tiles. Hidden cards are display:none (never
   focusable). Phones and short screens keep the tabs. app.js animates the change with a FLIP (see applyView).
   ============================================================= */
.tp-view { display: none; }
.btn[aria-pressed="true"].tp-view { background: var(--primary-soft); color: var(--primary-soft-ink); border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary); }
.btn[aria-pressed="true"].tp-view .tp-btn__txt::before { content: "\2713" / ""; margin-right: 6px; font-size: .85em; }
@media (min-width: 601px) and (min-height: 521px) {
  .app[data-mode="lc"] .tp-view { display: inline-flex; }
  .app[data-mode="lc"] .left { display: contents; }
  .app[data-mode="lc"] .stage { grid-template-columns: minmax(0, .8fr) minmax(0, 1.4fr); grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "graph side" "trans trans"; }
  .app[data-mode="lc"] .graph { grid-area: graph; }
  .app[data-mode="lc"] .side { grid-area: side; grid-template-rows: minmax(0, 1fr); }
  .app[data-mode="lc"] .transport { grid-area: trans; }
  .app[data-mode="lc"][data-graph="off"] .graph, .app[data-mode="lc"][data-box="off"] .box { display: none; }
  .app[data-mode="lc"][data-graph="off"] .stage { grid-template-columns: minmax(0, 1fr); grid-template-areas: "side" "trans"; }
  .app[data-mode="lc"][data-graph="on"][data-box="on"] .stage { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); }
  .app[data-mode="lc"][data-box="on"] .side { grid-template-rows: minmax(0, 1.7fr) minmax(0, 1fr); }
}
@media (min-width: 601px) and (max-width: 900px) and (min-height: 521px) {
  .app[data-mode="lc"] .stage, .app[data-mode="lc"][data-graph="on"][data-box="on"] .stage { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, .8fr) minmax(0, 1.2fr) auto; grid-template-areas: "graph" "side" "trans"; }
  .app[data-mode="lc"][data-graph="off"] .stage { grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "side" "trans"; }
  .app[data-mode="lc"] .side { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); }
  .app[data-mode="lc"][data-box="on"] .side { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
}
@media (max-width: 1100px) { .tp-view .tp-btn__txt { display: none; } .tp-view { width: var(--control-h); padding: 0; } }
