/* Capsule 01 · "Who draws the pixels?" explorer. Loaded with figures/pixels.js, on capsule 01 only. */

.px-fams { position: relative; margin-bottom: 18px; }
/* The family picker's legend is for assistive technology; the buttons speak for themselves on screen. */
.px-fams > legend { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.px-cross { position: relative; display: inline-flex; gap: 6px; }
/* The cross-platform bracket: RN and Flutter are one family with two hands on the pixels. */
.px-cross__label { display: none; }
@container fx (min-width: 640px) {
  .px-fams { padding-top: 18px; }
  .px-fams > legend { position: absolute; top: 0; left: 0; margin: 0; }
  .px-cross__label {
    display: block; position: absolute; left: 4px; right: 4px; top: -15px; height: 9px;
    border: 1px solid var(--fw); border-bottom: 0; border-radius: 7px 7px 0 0; opacity: .7;
    font: 700 .62rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--fw); text-align: center;
  }
  .px-cross__label span { position: relative; top: -6px; padding: 0 6px; background: var(--surface); }
}

/* ---------- Body: the phone, the gap where the pixels travel, the layers ---------- */
.px-body { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: clamp(56px, 10cqi, 120px); align-items: center; }
.px-phonecol { position: relative; z-index: 1; display: grid; justify-items: center; gap: 10px; }
.px-phone { --w: clamp(156px, 26cqi, 236px); }
.px-count { margin: 0; min-height: 2.6em; max-width: calc(var(--w, 200px) + 40px); text-align: center; font-size: .8rem; line-height: 1.3; color: var(--ink-3); transition: opacity var(--fx-t-short) ease; }
.px-count, .px-q__a, .px-caption { text-wrap: balance; }
.px-count b { display: block; font: 700 1.5rem/1.1 var(--font-mono); color: var(--fx-bounds); font-variant-numeric: tabular-nums; }
.px-count[hidden] { display: block; visibility: hidden; }

/* Beside the phone: the layers, then the two questions and the two controls (the right gutter carries the request). */
.px-side { position: relative; z-index: 1; min-width: 0; display: grid; gap: 16px; align-content: center; }
.px-stack { position: relative; z-index: 1; list-style: none; margin: 0; padding: 0 34px 0 0; display: grid; gap: 12px; }
.px-plate {
  --c: var(--rule-strong);
  position: relative; margin: 0; padding: 10px 12px 11px 17px; min-height: 72px;
  border-radius: 13px; border: 1px solid var(--rule); background: var(--fx-plate);
  box-shadow: 0 1px 2px rgba(22, 22, 31, .04);
  transition: opacity var(--fx-t-med) ease, transform var(--fx-t-med) var(--fx-ease-out), border-color var(--fx-t-short) ease, box-shadow var(--fx-t-short) ease, background-color var(--fx-t-short) ease;
}
.px-plate::before { content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 4px; border-radius: 4px; background: var(--c); transition: background-color var(--fx-t-short) ease, opacity var(--fx-t-short) ease; }
.px-plate b { display: block; font: 700 .7rem/1.3 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--c); margin-bottom: 2px; transition: color var(--fx-t-short) ease; }
.px-plate > span { display: block; font-size: .9rem; line-height: 1.42; color: var(--ink-2); }
.px-plate .px-txt { transition: opacity var(--fx-t-micro) ease; }
.px-plate.is-swap .px-txt { opacity: 0; }
.px-plate--you { --c: var(--you); background: color-mix(in srgb, var(--you) 7%, var(--fx-plate)); }
.px-plate--kit, .px-plate--os { --c: var(--os); }
.px-plate--os { background: color-mix(in srgb, var(--os) 7%, var(--fx-plate)); }
.px-plate--mid.is-fw { --c: var(--fw); background: color-mix(in srgb, var(--fw) 8%, var(--fx-plate)); }
.px-plate--mid.is-web { --c: var(--web); background: color-mix(in srgb, var(--web) 7%, var(--fx-plate)); }
.px-plate.is-empty { background: transparent; border-style: dashed; border-color: var(--rule-strong); box-shadow: none; }
.px-plate.is-empty::before { opacity: 0; }
.px-plate.is-empty b { color: var(--ink-3); }
.px-plate.is-idle { opacity: .7; }
.px-plate.is-idle b { color: var(--ink-3); }
.px-plate.is-idle::before { background: var(--rule-strong); }
/* The layer that draws: the screen green on its edge, and the badge (as on the static figure). */
.px-plate.is-draws { border-color: var(--screen); box-shadow: inset 0 0 0 1px var(--screen), 0 0 0 5px color-mix(in srgb, var(--screen) 11%, transparent); }
.px-plate.is-draws::after {
  content: attr(data-draws); position: absolute; right: 10px; top: -10px;
  font: 700 .64rem/1.3 var(--font-body); letter-spacing: .08em; text-transform: uppercase;
  color: var(--on-accent); background: var(--screen); padding: 3px 8px; border-radius: 999px; white-space: nowrap;
  animation: px-badge var(--fx-t-short) var(--fx-ease-pop) both;
}
:root[data-theme="dark"] .px-plate.is-draws::after { color: #0d1a14; }
@media (prefers-color-scheme: dark) { :root:not([data-theme]) .px-plate.is-draws::after { color: #0d1a14; } }
@keyframes px-badge { from { opacity: 0; transform: translateY(4px) scale(.8); } }
.px-plate.is-gate-hit { box-shadow: inset 0 0 0 1px var(--c), 0 0 0 5px color-mix(in srgb, var(--c) 14%, transparent); }
.px-plate.is-draws.is-gate-hit { box-shadow: inset 0 0 0 1px var(--screen), 0 0 0 5px color-mix(in srgb, var(--c) 18%, transparent); }

/* First entrance: the layers rise in, one after another. */
.px.is-pre .px-plate { opacity: 0; transform: translateY(14px); }
.px.is-pre .px-app, .px.is-pre .px-count { opacity: 0; }

/* ---------- The wires: pixels from the drawing layer to the screen; the request down to the OS ---------- */
.px-wires { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 0; }
.px-beam-glow { fill: none; stroke: var(--screen); stroke-width: 10; stroke-linecap: round; opacity: .12; }
.px-beam { fill: none; stroke: var(--screen); stroke-width: 2; stroke-linecap: round; }
.px-askline { fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-dasharray: 2 5; stroke-linecap: round; opacity: .7; }
.px-gate { fill: var(--surface); stroke: var(--c, var(--ink-3)); stroke-width: 2; }
.px-gate-label { font: 600 11px/1 var(--font-mono); fill: var(--ink-3); }
.px-dot { position: absolute; left: 0; top: 0; width: 7px; height: 7px; border-radius: 50%; background: var(--screen); box-shadow: 0 0 10px 2px color-mix(in srgb, var(--screen) 55%, transparent); offset-rotate: 0deg; opacity: 0; pointer-events: none; z-index: 0; }
.px.is-flow .px-dot { animation: px-flow 1.8s linear infinite; }
.px.is-flow .px-dot:nth-of-type(2) { animation-delay: -.6s; }
.px.is-flow .px-dot:nth-of-type(3) { animation-delay: -1.2s; }
.px.is-paused .px-dot { animation-play-state: paused; }
@keyframes px-flow { 0% { offset-distance: 0%; opacity: 0; } 12% { opacity: 1; } 85% { opacity: 1; } 100% { offset-distance: 100%; opacity: 0; } }

.px-packet {
  position: absolute; left: 0; top: 0; z-index: 2; display: grid; place-items: center; width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%; background: var(--you); color: var(--bg); box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--you) 80%, transparent);
  opacity: 0; pointer-events: none;
}
.px-packet svg { width: 16px; height: 16px; }
.px-packet.is-back { background: var(--screen); }

/* ---------- The app on the screen: the same app, three ways of being drawn ---------- */
.px-app { position: absolute; inset: 9% 0 0; padding: .55em .6em; display: grid; gap: .5em; align-content: start; transition: opacity var(--fx-t-short) ease; }
.px-h { display: block; width: 34%; height: .62em; margin: .35em 0 .1em .2em; border-radius: 1em; }
.px-app .w, .fx-sb .w { position: relative; }
.px-bar { display: flex; align-items: center; gap: .5em; height: 2.3em; padding: 0 .65em; border-radius: .65em; }
.px-bar__t { display: block; width: 46%; height: .5em; border-radius: 1em; }
.px-bar__ic { display: block; margin-left: auto; width: 1.15em; height: 1.15em; border-radius: 50%; }
.px-row { display: flex; align-items: center; gap: .55em; height: 2.7em; padding: 0 .6em; border-radius: .65em; }
.px-av { display: block; flex: none; width: 1.25em; height: 1.25em; border-radius: 50%; }
.px-lines { flex: 1; display: grid; gap: .32em; }
.px-l1, .px-l2 { display: block; height: .4em; border-radius: 1em; }
.px-l1 { width: 74%; } .px-l2 { width: 46%; height: .32em; }
.px-tg { display: block; flex: none; width: 1.95em; height: 1.08em; border-radius: 1em; }
.px-tg::before { content: ""; position: absolute; top: .14em; left: .14em; width: .8em; height: .8em; border-radius: 50%; background: #fff; }
.px-tg.is-on::before { left: auto; right: .14em; }
.px-card { position: relative; height: 6.4em; border-radius: .75em; overflow: hidden; }
.px-mtn { position: absolute; inset: auto 0 0; height: 62%; }
.px-mtn::before, .px-mtn::after { content: ""; position: absolute; bottom: 0; background: currentColor; }
.px-mtn::before { left: -5%; width: 70%; height: 100%; clip-path: polygon(0 100%, 48% 18%, 100% 100%); opacity: .55; }
.px-mtn::after { right: -8%; width: 75%; height: 78%; clip-path: polygon(0 100%, 52% 8%, 100% 100%); opacity: .8; }
.px-sun { position: absolute; top: 18%; left: 16%; width: .9em; height: .9em; border-radius: 50%; background: rgba(255, 255, 255, .85); }
.px-btn { display: none; height: 2.2em; border-radius: .5em; }
.px-app .px-fab { position: absolute; right: .8em; bottom: 4.3em; width: 2.5em; height: 2.5em; border-radius: 50%; display: grid; place-items: center; }
.px-app .px-nav { position: absolute; left: 0; right: 0; bottom: 0; height: 3.4em; display: flex; align-items: center; justify-content: space-around; padding: 0 1em .3em; }
.px-nav__i { display: block; width: 1.25em; height: 1.25em; border-radius: .4em; }
.px-fab i { display: block; width: 1em; height: 1em; background: linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat, linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat; }

/* Skin 1: the platform's own widgets (native, React Native): the films' dark app. Its accents are neutral, so no
   course colour (the OS sky, a browser engine violet…) appears as mere decoration. */
.skin-platform { color: #e9e8f4; }
.skin-platform .px-bar { background: #1d2038; }
.skin-platform .px-bar__t { background: #c9cbe0; }
.skin-platform .px-bar__ic { background: #3b3f63; }
.skin-platform .px-row { background: #171a2c; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05); }
.skin-platform .px-av { background: #262a44; box-shadow: inset 0 0 0 1.5px #8b8fb3; }
.skin-platform .px-l1 { background: #c9cbe0; } .skin-platform .px-l2 { background: #565b7d; }
.skin-platform .px-tg { background: #2c3050; } .skin-platform .px-tg.is-on { background: #8b93b8; }
.skin-platform .px-card { background: linear-gradient(135deg, #4b46d6, #8f5cff 48%, #ff6aa9); color: #2a1f6b; }
.skin-platform .px-h { background: #8b8fb3; }
.skin-platform .px-nav { background: #151829; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06); }
.skin-platform .px-nav__i { background: #3b3f63; } .skin-platform .px-nav__i:first-child { background: #c9cbe0; }
.skin-platform .px-fab { background: #e9e8f4; color: #151829; box-shadow: 0 0 0 .25em rgba(233, 232, 244, .14); }

/* Skin 2: Flutter's own painting: one canvas, its own look, identical on every phone. */
.px-screen.is-flutter { background: #fbf1f5; }
.skin-flutter { color: #3a1d2b; }
.skin-flutter .px-bar { background: #f6d6e3; border-radius: 1.1em; }
.skin-flutter .px-bar__t { background: #c2185b; }
.skin-flutter .px-bar__ic { background: #eaa9c2; }
.skin-flutter .px-row { background: #fff; border-radius: 1em; box-shadow: 0 .15em .5em rgba(194, 24, 91, .1); }
.skin-flutter .px-av { background: #ffd1e1; border-radius: .35em; }
.skin-flutter .px-l1 { background: #4a2738; } .skin-flutter .px-l2 { background: #d8b3c3; }
.skin-flutter .px-tg { background: #efc3d4; } .skin-flutter .px-tg.is-on { background: #e0457b; }
.skin-flutter .px-card { background: linear-gradient(160deg, #ff8fb1, #e0457b 60%, #8e2456); color: #5c1235; border-radius: 1.1em; }
.skin-flutter .px-fab { background: #e0457b; color: #fff; border-radius: .9em; }
.skin-flutter .px-h { background: #b07890; }
.skin-flutter .px-nav { background: #fff; border-radius: 1.4em 1.4em 0 0; box-shadow: 0 -.2em .8em rgba(194, 24, 91, .1); }
.skin-flutter .px-nav__i { background: #efc3d4; border-radius: 50%; } .skin-flutter .px-nav__i:first-child { background: #e0457b; }

/* Skin 3: a web page (hybrid, PWA): a page laid out by a browser engine. */
.px-screen.is-web { background: #f7f5f0; }
.skin-web { color: #1d1d27; padding-top: .4em; }
.skin-web .px-bar { background: transparent; height: 2.1em; padding: 0 .3em; border-radius: 0; border-bottom: 1px solid #e1ded6; }
.skin-web .px-bar__t { background: #1d1d27; width: 38%; height: .55em; }
.skin-web .px-bar__ic { background: linear-gradient(#1d1d27, #1d1d27) 0 20% / 100% 2px no-repeat, linear-gradient(#1d1d27, #1d1d27) 0 50% / 100% 2px no-repeat, linear-gradient(#1d1d27, #1d1d27) 0 80% / 100% 2px no-repeat; border-radius: 0; width: 1em; height: .9em; }
.skin-web .px-row { background: transparent; height: auto; padding: .15em .3em; border-radius: 0; }
.skin-web .px-av, .skin-web .px-tg, .skin-web .px-fab, .skin-web .px-nav { display: none; }
.skin-web .px-bar { order: 0; } .skin-web .px-h { order: 1; width: 82%; height: 1em; background: #1d1d27; margin: .5em .3em 0; border-radius: .2em; box-shadow: 0 1.35em 0 -.12em #1d1d27; margin-bottom: 1.2em; }
.skin-web .px-card { order: 2; } .skin-web .px-row { order: 3; } .skin-web .px-btn { order: 4; }
.skin-web .px-l1 { background: #3d3d4a; width: 92%; height: .36em; } .skin-web .px-l2 { background: #b8b5ad; width: 70%; height: .3em; }
.skin-web .px-card { background: linear-gradient(135deg, #cfd8e6, #9fb3cf); color: #6d84a8; border-radius: .35em; margin: .2em .3em 0; }
.skin-web .px-btn { display: block; background: #2f6fb5; margin: .1em .3em; }
.px-screen.is-web .fx-sb { color: #1d1d27; }
/* An installed PWA tints the status bar with its manifest's theme colour. */
.px-screen.is-pwa .fx-sb { background: #2f6fb5; color: #fff; }
.px-screen.is-flutter .fx-sb { color: #3a1d2b; }

/* Paint, as each family paints. The order of things appearing IS the lesson. */
/* The system draws view by view: each widget arrives on its own. */
.px-screen.paint-pop .px-app .w { animation: px-pop .42s var(--fx-ease-out) both; animation-delay: calc(var(--i, 0) * 34ms); }
@keyframes px-pop { from { opacity: 0; transform: scale(.9); } }
/* One engine paints one surface: a single brush stroke across the canvas. */
.px-wipe { position: absolute; inset: 9% 0 0; z-index: 1; background: #fbf1f5; transform: translateX(118%); visibility: hidden; pointer-events: none; }
.px-screen.paint-wipe .px-wipe { visibility: visible; }
.px-brush { position: absolute; left: -.5em; top: 40%; width: 1em; height: 3.2em; border-radius: 1em; background: linear-gradient(#ff8fb1, #e0457b); box-shadow: 0 0 1.2em #ff8fb1; transform: rotate(14deg); }
.px-screen.paint-wipe .px-wipe { animation: px-wipe .85s var(--fx-ease-io) both; }
@keyframes px-wipe { from { transform: translateX(0); } to { transform: translateX(118%); } }
/* A browser engine loads and lays out the page, top to bottom. */
.px-load { position: absolute; z-index: 2; left: 0; top: 9%; height: 2px; width: 100%; background: #2f6fb5; transform-origin: 0 50%; transform: scaleX(0); opacity: 0; }
.px-screen.paint-load .px-load { animation: px-load .7s var(--fx-ease-out) both; }
@keyframes px-load { 0% { transform: scaleX(0); opacity: 1; } 80% { transform: scaleX(1); opacity: 1; } 100% { transform: scaleX(1); opacity: 0; } }
.px-screen.paint-load .px-app .w { animation: px-fade .3s ease both; animation-delay: calc(140ms + var(--i, 0) * 26ms); }
@keyframes px-fade { from { opacity: 0; } }

/* Show layout bounds: red rectangles, blue corners, as Android draws them. */
.px-screen .w::after, .px-app::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  border: 1px solid var(--fx-bounds);
  background:
    linear-gradient(var(--fx-corner), var(--fx-corner)) 0 0 / 6px 2px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 0 0 / 2px 6px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 100% 0 / 6px 2px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 100% 0 / 2px 6px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 0 100% / 6px 2px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 0 100% / 2px 6px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 100% 100% / 6px 2px no-repeat,
    linear-gradient(var(--fx-corner), var(--fx-corner)) 100% 100% / 2px 6px no-repeat;
  transition: opacity .18s linear;
}
.px-screen.is-bounds .px-app::after, .px-screen.is-bounds .fx-sb .w::after { opacity: 1; }
.px-screen.is-bounds.is-many .px-app .w::after { opacity: 1; transition-delay: calc(var(--i, 0) * 22ms); }
.px-screen.is-bounds.is-one .px-app::after { animation: px-onebox .5s var(--fx-ease-out) both; }
@keyframes px-onebox { from { transform: scale(.94); opacity: 0; } }

/* ---------- Readout: the two questions, answered ---------- */
.px-readout { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 4px 34px 0 0; }
.px-q { position: relative; padding: 12px 14px 13px; border-radius: 13px; background: var(--fx-plate); border: 1px solid var(--rule); transition: border-color var(--fx-t-short) ease, box-shadow var(--fx-t-short) ease; }
.px-q__k { display: flex; align-items: center; gap: 8px; font: 700 .7rem/1.3 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.px-q__k i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.px-q--draw .px-q__k i { background: var(--screen); }
.px-q--talk .px-q__k i { background: var(--os); }
.px-q__a { margin: 5px 0 0 !important; font-size: 1rem !important; line-height: 1.45; color: var(--ink); transition: opacity var(--fx-t-micro) ease; }
.px-q.is-swap .px-q__a { opacity: 0; }
.px-q.is-hit { border-color: var(--os); box-shadow: 0 0 0 4px color-mix(in srgb, var(--os) 12%, transparent); }
.px-chain { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 8px; }
.px-chain .fx-chip { padding: 3px 7px; font-size: .72rem; transition: background-color var(--fx-t-micro) ease, border-color var(--fx-t-micro) ease, color var(--fx-t-micro) ease; }
.px-chain .fx-chip.is-lit { background: var(--os); border-color: var(--os); color: var(--bg); }
.px-chain i { font-style: normal; color: var(--ink-3); font-size: .8rem; }

.px-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 18px; margin: 0 34px 0 0; }
.px-tools .fx-switch input:checked { background: var(--fx-bounds); }
.px-caption { min-height: 3em; }
.px-caption b { color: var(--ink-2); }

/* ---------- Narrow: the phone above, the layers below; wires run in the gutters ---------- */
@container fx (max-width: 639px) {
  .px-body { grid-template-columns: minmax(0, 1fr); row-gap: 26px; }
  /* The variable and its effect on one screen: the two answers come right under the family tabs, then the phone,
     the layers and the controls (r2-review-pedagogy S5). */
  .px-side { display: contents; }
  .px-readout { order: -1; }
  .px-phonecol { order: 0; }
  .px-stack { order: 1; }
  .px-tools { order: 2; }
  .px-phone { --w: min(54cqi, 214px); }
  .px-stack { padding: 0 30px 0 26px; }
  .px-readout { grid-template-columns: 1fr; margin: 0 30px 0 26px; }
  .px-tools { margin: 0 30px 0 26px; }
  .px-tools { flex-direction: column; align-items: stretch; }
  .px-tools .fx-btn { width: 100%; }
}

/* Presentation mode: the figure fills the slide; text grows with it. */
[data-teaching="true"] .px-phone { --w: 172px; }
[data-teaching="true"] .px .fx__kicker { display: none; }
[data-teaching="true"] .px .fx__stage { padding: 16px 22px 14px; }
[data-teaching="true"] .px-fams { margin-bottom: 8px; }
[data-teaching="true"] .px-stack { gap: 8px; }
[data-teaching="true"] .px-plate { min-height: 0; padding-block: 7px 8px; }
[data-teaching="true"] .px-caption { min-height: 0; margin-top: 8px; }
[data-teaching="true"] .px-count[hidden] { display: none; }
[data-teaching="true"] .px-side { gap: 10px; }
[data-teaching="true"] .px-plate > span { font-size: 1rem; }

/* No JS, or on paper: the static figure kept in the page (five families, one line each) instead of the explorer. */
@media print { .px > .fx-fallback[hidden] { display: grid !important; } .px > .fx__stage { display: none !important; } }
