/* =========================================================================
   The Alpha Trap — tool-specific styling
   -------------------------------------------------------------------------
   Loaded after assets/css/main.css and components/interactive-shell.css, and
   uses their design tokens throughout. Nothing here redefines a token, so the
   light and dark palettes, the focus treatment and the forced-colours
   behaviour of the shared files all continue to apply.

   Only two shared rules are overridden, both in one place and both explained
   where they appear: the width of the shell's controls column (this tool's
   controls are 24 sentences, not four sliders), and the two-column .split,
   which needs equal columns here rather than the 3fr/2fr used on landing
   pages.
   ========================================================================= */

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

/* Equal columns for the debrief and challenge pairs. The site default (3fr
   2fr) is right for "content plus sidebar"; these are two peers. */
@media (min-width: 56em) {
  .split--wide {
    grid-template-columns: 1fr 1fr;
  }
}

/* Both children of the shell's grid must be allowed to shrink below their
   own min-content width. Without this, a grid item's automatic minimum size
   is its min-content — and the coverage table's min-content is about 248px,
   which pushed the shared single-column track wider than the viewport at
   320px. The overflow was then invisibly clipped by the `overflow: hidden`
   on .interactive rather than showing as a scrollbar. The table scrolls
   inside its own .table-scroll container instead. */
#alpha-trap .interactive__controls,
#alpha-trap .interactive__stage {
  min-width: 0;
}

/* The shell gives its controls column minmax(15rem, 20rem), which suits a
   panel of sliders. The item bank is 24 full sentences and needs more room,
   so the proportions are restated here rather than fought with. */
@media (min-width: 52em) {
  #alpha-trap .interactive__body {
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  }
}

@media (min-width: 72em) {
  #alpha-trap .interactive__body {
    grid-template-columns: minmax(0, 26rem) minmax(0, 1fr);
  }
}

/* -------------------------------------------------------------------------
   Introductory panels
   ---------------------------------------------------------------------- */

.how-to {
  padding-left: 1.2rem;
  font-size: var(--text-sm);
}

.how-to > li {
  margin-top: var(--space-2);
}

/* -------------------------------------------------------------------------
   Prediction panel
   ---------------------------------------------------------------------- */

.prediction {
  display: grid;
  gap: var(--space-5);
  max-width: 46rem;
}

.prediction__group {
  margin: 0;
  padding: 0;
  border: 0;
}

.prediction__legend {
  padding: 0;
  margin-bottom: var(--space-2);
  font-weight: 650;
  font-size: var(--text-base);
}

/* .control--choice comes from the interactive shell, which scopes it inside
   .interactive. These panels sit outside the shell, so the sizing that makes
   the whole row a 44px target is repeated here. */
.prediction .control--choice,
.challenge .control--choice {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  font-size: var(--text-sm);
  cursor: pointer;
}

.prediction .control--choice input,
.challenge .control--choice input {
  width: 1.15rem;
  height: 1.15rem;
  flex: none;
  accent-color: var(--colour-accent);
}

.prediction__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.prediction__error {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--colour-status-border);
  border-left: 4px solid var(--colour-status-border);
  border-radius: var(--radius-sm);
  background-color: var(--colour-status-bg);
  color: var(--colour-status-text);
  font-size: var(--text-sm);
}

.prediction__readback {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
  background-color: var(--colour-surface-raised);
  font-size: var(--text-sm);
}

.goal__label {
  flex: none;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

.goal__text {
  flex: 1 1 16rem;
}

.goal strong {
  font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------------------
   Item bank
   ---------------------------------------------------------------------- */

/* The scale, as a read-only list. An item that repeats another's wording is
   marked by a left rule, a tinted ground AND the words "another way of asking
   ...", so the marking never rests on colour. */
.scale {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}

.scale__item {
  display: grid;
  grid-template-columns: minmax(5.5rem, auto) 1fr;
  gap: 0.15rem 0.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--colour-border);
  border-left: 4px solid var(--colour-border);
  border-radius: var(--radius-sm);
  background: var(--colour-surface);
}

.scale__item[data-repeated="yes"] {
  border-left-color: var(--colour-warning, #b8860b);
  background: var(--colour-surface-alt, var(--colour-surface));
}

.scale__area {
  grid-column: 1;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

.scale__text {
  grid-column: 2;
}

.scale__tag {
  grid-column: 2;
  font-size: 0.82rem;
  color: var(--colour-text-muted);
}

@media (max-width: 30rem) {
  .scale__item {
    grid-template-columns: 1fr;
  }
  .scale__area,
  .scale__text,
  .scale__tag {
    grid-column: 1;
  }
}

@media (forced-colors: active) {
  .scale__item[data-repeated="yes"] {
    border-left-color: Highlight;
  }
}

/* -------------------------------------------------------------------------
   Stage contents
   ---------------------------------------------------------------------- */

.stage__heading {
  margin: 0;
  font-size: var(--text-base);
}

/* The alpha figure is the phenomenon; let it dominate the readout. */
.interactive__readout dd[data-metric="alpha"] {
  font-size: var(--text-2xl);
  line-height: 1.1;
  color: var(--colour-accent);
}

.chart {
  margin: 0;
  display: grid;
  gap: var(--space-3);
}

.chart__caption {
  font-size: var(--text-sm);
  font-weight: 650;
}

.chart__svg {
  max-width: 32rem;
}

/* Bars are filled with the accent, and the portion of each area made up of
   repeated wording is overlaid with a hatch. Neither carries meaning on its
   own: every bar is labelled with its own count in text, and the table below
   repeats all of it. */
.chart__bar {
  fill: var(--colour-accent-soft);
  stroke: var(--colour-accent);
  stroke-width: 1;
}

.chart__bar-repeat {
  fill: url(#alpha-trap-hatch);
  stroke: var(--colour-accent);
  stroke-width: 1;
}

.chart__hatch {
  stroke: var(--colour-accent);
  stroke-width: 2;
}

.chart__baseline {
  stroke: var(--colour-border);
  stroke-width: 1;
}

.chart__label,
.chart__count {
  fill: var(--colour-text);
  font-family: var(--font-body);
  font-size: 13px;
}

.chart__count {
  fill: var(--colour-text-muted);
  font-variant-numeric: tabular-nums;
}

/* The Round 2 requirements, ticked off live. "(met)" / "(not yet)" is written
   into the text by tool.js, so the state is never carried by the marker
   alone. */
.goal__checks {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  display: grid;
  gap: 0.15rem;
}

.goal__checks > li {
  margin-top: 0;
  padding-left: 1.4rem;
  position: relative;
}

.goal__checks > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.35em;
  width: 0.6rem;
  height: 0.6rem;
  border: 2px solid var(--colour-border-strong);
  border-radius: 2px;
}

.goal__checks > li[data-met="yes"]::before {
  border-color: var(--colour-accent);
  background-color: var(--colour-accent);
}

/* -------------------------------------------------------------------------
   Tables
   ---------------------------------------------------------------------- */

.table-scroll {
  overflow-x: auto;
}

.data-table,
.chart__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.data-table th,
.data-table td,
.chart__table th,
.chart__table td {
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--colour-border);
  text-align: left;
  vertical-align: top;
  color: var(--colour-text);
}

.data-table thead th,
.chart__table thead th {
  background-color: var(--colour-surface);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

.data-table td,
.chart__table td {
  font-variant-numeric: tabular-nums;
}

.chart__table tbody th {
  font-weight: 550;
}

/* -------------------------------------------------------------------------
   Verdict boxes (redundancy, outcome correlation)
   -------------------------------------------------------------------------
   The tone is carried by a word in the text as well as by the border, so the
   distinction survives greyscale, forced colours and a screen reader.
   ---------------------------------------------------------------------- */

.verdict {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--colour-border);
  border-left: 4px solid var(--colour-border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--colour-surface);
}

.verdict__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

.verdict__body {
  margin: 0;
  font-size: var(--text-sm);
}

.verdict__body + .verdict__body {
  margin-top: var(--space-2);
}

.verdict__note {
  margin: var(--space-2) 0 0;
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

.verdict[data-tone="warn"] {
  border-left-color: var(--colour-social-critical-psychology);
}

.verdict[data-tone="caution"] {
  border-left-color: var(--colour-cognitive);
}

.verdict[data-tone="good"] {
  border-left-color: var(--colour-neuropsychology);
}

.verdict--outcome {
  background-color: var(--colour-accent-soft);
}

/* -------------------------------------------------------------------------
   Reveal and comparison
   ---------------------------------------------------------------------- */

.reveal > :last-child,
.feedback > :last-child {
  margin-bottom: 0;
}

.reveal__lead {
  font-size: var(--text-lg);
  font-weight: 600;
}

.reveal__figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-3);
  margin: var(--space-4) 0;
  padding: 0;
  list-style: none;
}

.reveal__figures > li {
  margin-top: 0;
  padding: var(--space-3);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
  background-color: var(--colour-surface-raised);
}

.reveal__figure-label {
  display: block;
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

.reveal__figure-value {
  display: block;
  font-size: var(--text-xl);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.reveal__items {
  font-size: var(--text-sm);
  padding-left: 1.2rem;
}

/* -------------------------------------------------------------------------
   Challenges
   ---------------------------------------------------------------------- */

.challenge {
  display: grid;
  gap: var(--space-4);
  align-content: start;
}

.challenge__locked {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--colour-text-muted);
}

.feedback {
  padding: var(--space-4);
  border: 1px solid var(--colour-border-strong);
  border-left: 4px solid var(--colour-border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--colour-surface-raised);
  font-size: var(--text-sm);
}

.feedback[data-tone="good"] {
  border-left-color: var(--colour-neuropsychology);
}

.feedback[data-tone="caution"] {
  border-left-color: var(--colour-cognitive);
}

.feedback__verdict {
  font-weight: 700;
}

/* -------------------------------------------------------------------------
   Caution panel
   ---------------------------------------------------------------------- */

.panel--caution {
  background-color: var(--colour-status-bg);
  border-color: var(--colour-status-border);
}

.panel--caution li + li {
  margin-top: var(--space-3);
}

/* -------------------------------------------------------------------------
   Forced colours
   -------------------------------------------------------------------------
   Same reasoning as the block in components/interactive-shell.css: anything
   whose boundary or state was carried by a background tint has to be redrawn
   with a system colour keyword, because author backgrounds are discarded.
   ---------------------------------------------------------------------- */

@media (forced-colors: active) {
  .goal,
  .verdict,
  .feedback,
  .prediction__error,
  .prediction__readback,
  .scale__item,
  .reveal__figures > li {
    border: 1px solid CanvasText;
  }
}

/* -------------------------------------------------------------------------
   Activity utilities
   -------------------------------------------------------------------------
   A quiet row beneath an activity holding the two controls that are about
   using the activity rather than about the psychology: Full screen, and Copy
   activity HTML. Deliberately understated, because neither is part of the
   learner's path through the page.

   The two have different fates in an export. Copy activity HTML is a control
   of this website and its block carries data-activity-export, which is how
   scripts/build-standalone.py finds and removes it - a copy must not arrive
   carrying a button that looks for a file no longer beside it. Full screen is
   a usability control and travels with the copy.
   ---------------------------------------------------------------------- */

.activity-utilities {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3) var(--space-4);
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px dashed var(--colour-border);
  border-radius: var(--radius-sm);
}

.activity-utilities button {
  min-height: 2.75rem;
  padding: 0.4rem 1rem;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--colour-text);
  background-color: var(--colour-surface);
  border: 1px solid var(--colour-border-strong, var(--colour-border));
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.activity-utilities button:hover {
  background-color: var(--colour-page);
}

/* Never disabled mid-copy: disabling a focused control drops focus to <body>
   and a disabled button cannot be given it back. Copy carries aria-busy
   instead, and is truly disabled only where fetch is unavailable and the copy
   can never work. */
.activity-utilities button[aria-busy="true"] {
  cursor: progress;
}

.activity-utilities button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Confirmation state. The tick in the label carries the meaning; the colour
   only reinforces it, so nothing is lost when colour is unavailable. */
.activity-utilities button[data-copy-state="ok"] {
  border-color: var(--colour-neuropsychology);
  box-shadow: inset 0 0 0 1px var(--colour-neuropsychology);
}

/* Pressed state for Full screen. aria-pressed carries this for assistive
   technology and the label itself changes to "Exit full screen", so the inset
   line is an echo rather than the only signal. */
.activity-utilities button[aria-pressed="true"] {
  border-color: var(--colour-accent);
  box-shadow: inset 0 0 0 1px var(--colour-accent);
}

/* The two controls that belong to this website rather than to the activity.
   Both are removed from an exported copy; Full screen, which sits outside this
   wrapper, is not. */
.activity-utilities__lecturer {
  display: flex;
  flex: 1 1 20rem;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3) var(--space-4);
}

/* Download is a link rather than a button, because it points at a file and the
   browser fetches it: there is nothing for a script to do. That keeps it
   working where JavaScript does not, and it guarantees the bytes are the
   committed standalone.html rather than anything reassembled at press time.
   The cost is that it has to be told to size and look like the buttons it
   stands next to. */
.activity-utilities__download {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.4rem 1rem;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--colour-text);
  text-decoration: none;
  background-color: var(--colour-surface);
  border: 1px solid var(--colour-border-strong, var(--colour-border));
  border-radius: var(--radius-sm);
}

/* Presented as a button among buttons, so the underline is dropped at rest and
   brought back on hover and focus rather than given up altogether. */
.activity-utilities__download:hover,
.activity-utilities__download:focus-visible {
  background-color: var(--colour-page);
  text-decoration: underline;
}

.activity-utilities__note {
  flex: 1 1 16rem;
  margin: 0;
  font-size: var(--text-sm);
  color: var(--colour-text-muted);
}

@media (forced-colors: active) {
  .activity-utilities button {
    border: 1px solid ButtonBorder;
  }

  .activity-utilities button[aria-pressed="true"] {
    border: 2px solid Highlight;
  }

  .activity-utilities__download {
    color: LinkText;
    border: 1px solid LinkText;
  }
}

/* -------------------------------------------------------------------------
   Full-screen state
   -------------------------------------------------------------------------
   The element put full screen is the exported `.opi-activity` wrapper where
   there is one, and this site's <main> otherwise - never <body>, which would
   take the header and footer with it.

   A full-screen element is sized to the screen and clips what overflows, so
   an activity taller than the display needs `overflow-y: auto` or its debrief
   becomes unreachable. It also needs a background of its own: the default
   backdrop is black, and these panels assume the page colour behind them.
   ---------------------------------------------------------------------- */

.opi-activity:fullscreen,
main:fullscreen,
.interactive:fullscreen {
  overflow-y: auto;
  overscroll-behavior: contain;
  background-color: var(--colour-page);
  color: var(--colour-text);
}

main:fullscreen > .section:first-child,
.opi-activity:fullscreen > .section:first-child {
  padding-top: var(--space-5);
}

/* -------------------------------------------------------------------------
   Optional learner support
   -------------------------------------------------------------------------
   The "Need a hand?" and "Key terms" disclosures. Both are deliberately
   subordinate to the activity: smaller type, no fill, a plain summary rather
   than a button. Collapsed, either one is a single line, and a learner who
   does not need it reads past it.

   Two shapes use these rules:

     .helper[data-learner-help]  a guide plus a nested "Key terms" list. The
                                 attribute is what components/learner-help.js
                                 binds to.
     .helper                     "Key terms" alone, with no script at all.

   Sixteen activities have the guide; the rest that have support carry the
   glossary only, because a guide there would restate what the page already
   says. See docs/adapting-a-tool.md.
   ---------------------------------------------------------------------- */

.helper {
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
}

.helper__summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.75rem;
  padding: 0 var(--space-2);
  font-weight: 600;
  color: var(--colour-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.helper__summary:hover {
  color: var(--colour-text);
}

.helper[open] > .helper__summary {
  color: var(--colour-text);
}

.helper__body {
  margin: var(--space-2) 0 0;
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--colour-border-strong);
  background-color: var(--colour-surface);
  border-radius: var(--radius-sm);
}

.helper__offer {
  margin: 0;
}

.helper__start,
.helper__actions button {
  min-height: 2.75rem;
  padding: 0.4rem 1rem;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--colour-on-accent);
  background-color: var(--colour-accent);
  border: 1px solid var(--colour-accent);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.helper__actions button[data-variant="secondary"] {
  color: var(--colour-text);
  background-color: transparent;
  border-color: var(--colour-border-strong);
}

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

.helper__progress {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

/* The step is the one thing in here that should read as prose.

   min-height reserves two lines. Without it a step that wraps to a second line
   makes the panel taller and pushes the activity down by a line, so the thing
   the learner has just been told to look at moves as they press Next. Every
   step in the collection is written to fit two lines at a normal reading
   width, which is what makes one shared reservation workable. */
.helper__step {
  margin: 0 0 var(--space-3);
  max-width: 42rem;
  min-height: 3.4em;
}

/* On a phone the same sentences wrap to as many as four lines, so two is not
   enough to hold the panel still. Reserving four costs some blank space under
   the shorter steps and buys an activity that does not move under the reader. */
@media (max-width: 40em) {
  .helper__step {
    min-height: 6.8em;
  }
}

.helper__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.helper__aside {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

/* The nested glossary inside a guide. Where the glossary is the whole body,
   it needs no divider above it. */
.helper__terms {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--colour-border);
}

.helper__glossary {
  margin: var(--space-2) 0 0;
  display: grid;
  gap: var(--space-2);
}

.helper__body > .helper__glossary {
  margin-top: 0;
}

.helper__glossary dt {
  font-weight: 650;
}

.helper__glossary dd {
  margin: 0 0 var(--space-2);
  max-width: 42rem;
  color: var(--colour-text-muted);
}

.helper__glossary dd:last-child {
  margin-bottom: 0;
}

/* The step's target. An outline is painted outside the box, so nothing on the
   page moves when it appears or goes - which matters because these sit beside
   charts that are expensive to reflow. Decoration only: every step names its
   target in words, so nothing depends on seeing this. */
[data-guide-target] {
  outline: 3px solid var(--colour-focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

@media (forced-colors: active) {
  [data-guide-target] {
    outline: 3px solid Highlight;
  }

  .helper__body {
    border-left: 3px solid CanvasText;
  }
}
