/* Capsule 03 · iOS: the states simulator, the doors map, the purpose-string simulator. Loaded with
   figures/ios-lifecycle.js, figures/ios-doors.js and figures/ios-purpose.js, on capsule 03 only.
   Each figure mounts beside its .fx-fallback (the static version), which shows without JavaScript and in print. */
.fx-fallback[hidden] { display: none; }
@media print {
  .fx-fallback[hidden] { display: block !important; }
  .fx > .fx__stage { display: none !important; }
}

/* ======================= States simulator ======================= */
.io-top { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: clamp(18px, 4cqi, 44px); align-items: start; }
.io-phone { --w: clamp(150px, 20cqi, 196px); }
.io-ui { position: absolute; inset: 0; }
.io-layer { position: absolute; inset: 0; transition: opacity .3s ease, transform .3s var(--fx-ease-out); }
.io-layer.is-off { opacity: 0; transform: scale(.96); visibility: hidden; pointer-events: none; transition: opacity .3s ease, transform .3s var(--fx-ease-out), visibility 0s linear .3s; }
.io-screen .fx-sb { color: #fff; }
.io-screen.is-light .fx-sb { color: #1d1d27; }

/* Home screen */
.io-home { padding: 3.2em 1.1em 1em; display: grid; grid-template-columns: repeat(4, 1fr); align-content: start; gap: 1.3em .7em;
  background: radial-gradient(90% 60% at 0% 10%, rgba(255, 61, 139, .45), transparent 60%), radial-gradient(80% 70% at 100% 40%, rgba(122, 92, 255, .5), transparent 60%), radial-gradient(90% 60% at 30% 100%, rgba(47, 125, 255, .45), transparent 60%), #141026; }
.io-ic { display: grid; justify-items: center; gap: .3em; font: 500 .52em/1.1 var(--font-body); color: rgba(255, 255, 255, .85); }
.io-ic i { display: block; width: 2.4em; height: 2.4em; border-radius: .62em; background: var(--c); }
.io-notes { all: unset; display: grid; justify-items: center; gap: .3em; cursor: pointer; font: 600 .52em/1.1 var(--font-body); color: #fff; -webkit-tap-highlight-color: transparent; }
.io-notes i { width: 2.4em; height: 2.4em; border-radius: .62em; background: linear-gradient(#ffd54a 0 30%, #fffdf3 30%); box-shadow: 0 .4em 1em rgba(0, 0, 0, .35), inset 0 0 0 1px rgba(0, 0, 0, .08); position: relative; }
.io-notes i::after { content: ""; position: absolute; left: 22%; right: 22%; top: 48%; height: 30%; background: repeating-linear-gradient(#c9c2a2 0 1px, transparent 1px 30%); }
.io-notes:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: .6em; }
.io-notes span, .io-ic span { font-size: 1em; }
.io-dock { position: absolute; left: .7em; right: .7em; bottom: 1.1em; height: 3.4em; border-radius: 1.3em; background: rgba(255, 255, 255, .18); display: flex; justify-content: space-around; align-items: center; }
.io-dock i { width: 2.3em; height: 2.3em; border-radius: .62em; background: var(--c); }

/* Launch screen: shown on a cold launch only. */
.io-launch { display: grid; place-items: center; background: #fffdf3; }
.io-launch i { width: 3.4em; height: 3.4em; border-radius: .9em; background: linear-gradient(#ffd54a 0 30%, #fffdf3 30%); box-shadow: 0 .3em 1em rgba(0, 0, 0, .12), inset 0 0 0 1px rgba(0, 0, 0, .08); }

/* The app */
.io-app { padding: 3em .9em 1em; background: #fffdf3; color: #1d1d27; display: flex; flex-direction: column; gap: .7em; }
.io-app__title { margin: 0 !important; font: 700 1.25em/1.1 var(--font-body) !important; color: #1d1d27; }
.io-app .io-back { font: 600 .62em/1 var(--font-body); color: #c7962b; }
.io-draft { font: 500 .95em/1.4 var(--font-body); color: #1d1d27; background: transparent; border: 0; border-top: 1px solid #ece6cf; padding: .7em 0 0; resize: none; min-height: 8em; width: 100%; }
.io-draft:focus { outline: 2px solid #c7962b; outline-offset: 2px; }
.io-draft::placeholder { color: #b9b29a; }
/* Another app, when the user switches away. */
.io-other { background: linear-gradient(160deg, #cfe9d8, #9fd3b5 40%, #e8efe3); }
.io-other::before { content: ""; position: absolute; inset: 0; background: linear-gradient(115deg, transparent 46%, #fff 46.5% 48.5%, transparent 49%), linear-gradient(20deg, transparent 58%, #fff 58.5% 60%, transparent 60.5%), linear-gradient(80deg, transparent 30%, rgba(255, 255, 255, .8) 30.5% 31.5%, transparent 32%); }
.io-other::after { content: ""; position: absolute; left: 50%; top: 45%; width: 1.2em; height: 1.2em; border-radius: 50% 50% 50% 0; transform: rotate(-45deg); background: #e5484d; box-shadow: 0 0 0 .3em rgba(229, 72, 77, .25); }
.io-home-ind { position: absolute; z-index: 3; left: 50%; bottom: 1.4%; width: 34%; height: .3em; border-radius: 1em; background: rgba(255, 255, 255, .7); transform: translateX(-50%); }
.io-screen.is-light .io-home-ind { background: rgba(29, 29, 39, .5); }

/* ---------- Side ---------- */
.io-side { display: grid; gap: 14px; min-width: 0; align-content: start; }
.io-mem-wrap { min-width: 0; }
.io-k.io-k--file { font-family: var(--font-mono); letter-spacing: .02em; text-transform: none; font-weight: 600; }
.io-k { display: block; margin: 0 0 6px; font: 700 .68rem/1.3 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.io-track { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
.io-track li { position: relative; margin: 0; padding: 8px 7px 9px; border-radius: 10px; border: 1px solid var(--rule); background: var(--fx-plate); min-width: 0; transition: background-color .25s ease, border-color .25s ease, transform .25s var(--fx-ease-out), box-shadow .25s ease, opacity .25s ease; }
.io-track b { display: block; font: 700 .76rem/1.2 var(--font-body); color: var(--os); }
.io-track span { display: block; margin-top: 3px; font-size: .7rem; line-height: 1.3; color: var(--ink-3); }
.io-track li[data-s="terminated"] { border-style: dashed; background: transparent; }
.io-track li.is-now { border-color: var(--screen); background: color-mix(in srgb, var(--screen) 12%, var(--surface)); transform: translateY(-2px); box-shadow: 0 0 0 3px color-mix(in srgb, var(--screen) 14%, transparent); }
.io-track li.is-now b { color: var(--ink); }
.io-track li[data-s="suspended"].is-now { border-color: #5aa9e6; background: linear-gradient(160deg, color-mix(in srgb, #8fd3ff 26%, var(--surface)), color-mix(in srgb, #5aa9e6 10%, var(--surface))); box-shadow: 0 0 0 3px rgba(90, 169, 230, .22); }
.io-track li[data-s="terminated"].is-now { border-color: var(--fx-kill); background: color-mix(in srgb, var(--fx-kill) 9%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-kill) 16%, transparent); }
/* The countdown: a few seconds in the background before the freeze. */
.io-ring { position: absolute; right: 6px; top: 6px; width: 18px; height: 18px; opacity: 0; transform: rotate(-90deg); }
.io-ring circle { fill: none; stroke: var(--os); stroke-width: 3; stroke-dasharray: 44 44; stroke-dashoffset: 0; }
.io-track li.is-counting .io-ring { opacity: 1; }
.io-track li.is-counting .io-ring circle { animation: io-count 1.5s linear forwards; }
@keyframes io-count { to { stroke-dashoffset: 44; } }

.io-mem { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 10px; }
.io-proc { padding: 10px 12px 12px; border-radius: 12px; border: 1.5px solid var(--you); background: color-mix(in srgb, var(--you) 6%, var(--fx-plate)); min-width: 0; transition: border-color .3s ease, background .3s ease; }
.io-proc.is-frozen { border-color: #5aa9e6; background: linear-gradient(160deg, color-mix(in srgb, #8fd3ff 22%, var(--fx-plate)), var(--fx-plate)); }
.io-proc.is-none { border-style: dashed; border-color: var(--rule-strong); background: transparent; }
.io-proc.is-cut { animation: io-cut .3s var(--fx-ease-in); }
@keyframes io-cut { 40% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--fx-kill) 30%, transparent); border-color: var(--fx-kill); } }
.io-proc__st { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; font: 600 .78rem/1.3 var(--font-body); color: var(--ink); }
/* CPU: the bars move while the app runs, and stop dead when it is suspended. */
.io-cpu { display: flex; align-items: flex-end; gap: 2px; height: 22px; }
.io-cpu i { width: 4px; height: 100%; border-radius: 2px; background: var(--you); transform-origin: 50% 100%; transform: scaleY(.15); }
.io-proc.is-run .io-cpu i { animation: io-cpu .9s ease-in-out infinite alternate; }
.io-proc.is-low .io-cpu i { animation-duration: 1.8s; opacity: .6; }
.io-cpu i:nth-child(2n) { animation-delay: -.3s !important; } .io-cpu i:nth-child(3n) { animation-delay: -.6s !important; } .io-cpu i:nth-child(5n) { animation-delay: -.45s !important; }
.io-proc.is-frozen .io-cpu i { background: #5aa9e6; animation: none; transform: scaleY(.08); }
.io-proc.is-none .io-cpu { opacity: 0; }
.fx.is-paused .io-cpu i { animation-play-state: paused; }
@keyframes io-cpu { from { transform: scaleY(.2); } to { transform: scaleY(1); } }
.io-store { padding: 10px 12px 12px; border-radius: 12px; border: 1px solid var(--rule); background: var(--fx-plate); min-width: 0; }
.io-val { display: inline-flex; max-width: 100%; padding: 4px 8px; border-radius: 7px; font: 600 .76rem/1.3 var(--font-mono); background: var(--surface); border: 1px solid var(--rule-strong); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.io-val.is-empty { color: var(--ink-3); border-style: dashed; background: transparent; font-weight: 500; }
.io-val.is-frozen { border-color: #5aa9e6; background: color-mix(in srgb, #8fd3ff 18%, var(--surface)); }

.io-controls { display: flex; flex-wrap: wrap; gap: 8px; }
.io-controls .fx-btn { flex: 1 1 auto; }
.io-story { border: 2px solid transparent; background: linear-gradient(var(--surface), var(--surface)) padding-box, linear-gradient(90deg, #ff3d8b, #7a5cff 55%, #2f7dff) border-box; color: var(--ink); }
.io-story:hover { border-color: transparent; background: linear-gradient(color-mix(in srgb, var(--accent) 6%, var(--surface)), color-mix(in srgb, var(--accent) 6%, var(--surface))) padding-box, linear-gradient(90deg, #ff3d8b, #7a5cff 55%, #2f7dff) border-box; }
.io-opts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 22px; }
.io-opts .fx-btn { margin-left: auto; }
.fx-ev--freeze { background: rgba(143, 211, 255, .14); color: #a9dcff; border-color: rgba(143, 211, 255, .45); font-family: var(--font-body); font-weight: 700; }
.fx-ev--wait { background: transparent; color: var(--code-dim); border-color: var(--code-rule); border-style: dashed; font-family: var(--font-body); font-weight: 500; }
.io-caption { margin: 10px 0 0 !important; min-height: 1.5em; font: 600 .82rem/1.4 var(--font-body) !important; letter-spacing: .02em; color: var(--accent); }

@container fx (max-width: 719px) {
  .io-top { grid-template-columns: auto minmax(0, 1fr); gap: 14px 14px; align-items: start; }
  .io-side { display: contents; }
  .io-phone { --w: min(42cqi, 168px); grid-area: 1 / 1; }
  .io-track { grid-area: 1 / 2; align-self: center; grid-template-columns: minmax(0, 1fr); gap: 5px; }
  .io-track li { padding: 6px 9px 7px; }
  .io-track li.is-now { transform: none; }
  .io-mem-wrap, .io-controls, .io-opts { grid-column: 1 / -1; }
  .io-controls .fx-btn { flex: 1 1 40%; }
  .io-opts .fx-btn { margin-left: 0; width: 100%; }
}

/* The log on a phone: the callback name on one line, its note under it (breaks only at the <wbr> in the long names). */
@container fx (max-width: 719px) {
  .io .fx-ev { flex-wrap: wrap; overflow-wrap: normal; font-size: .72rem; }
  .io .fx-ev small { flex-basis: 100%; }
}

/* ======================= Doors: every way onto an iPhone ======================= */
.dr-top { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.dr-map { position: relative; margin: 0; }
.dr-map svg { width: 100%; height: auto; overflow: visible; }
.dm { fill: none; stroke-linecap: round; stroke-width: 3.1; transition: stroke .5s ease, opacity .5s ease; }
.dm-land { stroke: var(--rule-strong); }
.dm-eu, .dm-jp, .dm-br { stroke: color-mix(in srgb, var(--os) 45%, var(--rule-strong)); cursor: pointer; }
.dr-hit { fill: transparent; cursor: pointer; }
.dr-hit:hover + .dm, .dr-hit:focus + .dm { stroke: var(--os); }
.dr-map[data-r="world"] .dm-land, .dr-map[data-r="world"] .dm-eu, .dr-map[data-r="world"] .dm-jp, .dr-map[data-r="world"] .dm-br { stroke: color-mix(in srgb, var(--ink) 55%, transparent); }
.dr-map[data-r="eu"] .dm-eu, .dr-map[data-r="jp"] .dm-jp, .dr-map[data-r="br"] .dm-br { stroke: var(--os); }
.dr-label { font: 700 13px/1 var(--font-body); fill: var(--ink-3); letter-spacing: .04em; pointer-events: none; transition: fill .3s ease; }
.dr-map[data-r="eu"] .dr-label[data-r="eu"], .dr-map[data-r="jp"] .dr-label[data-r="jp"], .dr-map[data-r="br"] .dr-label[data-r="br"] { fill: var(--os); }
.dr-ping { fill: none; stroke: var(--os); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.dr-ping.is-on { animation: dr-ping 1.6s var(--fx-ease-out) 2; }
@keyframes dr-ping { 0% { opacity: .9; transform: scale(.4); } 100% { opacity: 0; transform: scale(2.2); } }

/* The wall of doors. Each door is a leaf on a hinge: open where it exists, shut where it does not. */
.dr-wall { position: relative; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; margin-top: 18px; padding-top: 34px; }
.dr-key { position: absolute; left: 0; right: 0; top: 0; display: flex; align-items: center; gap: 10px; font: 700 .7rem/1.3 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); }
.dr-key::after { content: ""; flex: 1; height: 2px; border-radius: 2px; background: var(--wire); opacity: .8; }
.dr-key svg { width: 18px; height: 18px; color: var(--os); flex: none; }
.dr { --open: 0; display: grid; gap: 8px; align-content: start; min-width: 0; }
.dr__frame { position: relative; height: 128px; border-radius: 46px 46px 6px 6px; border: 2px solid var(--rule-strong); background: linear-gradient(180deg, color-mix(in srgb, var(--os) 18%, var(--surface)), color-mix(in srgb, var(--os) 46%, var(--surface)) 82%, color-mix(in srgb, var(--os) 62%, #fff)); overflow: hidden; transition: border-color .4s ease, box-shadow .4s ease; }
.dr__leaf { position: absolute; inset: 0; border-radius: 44px 44px 4px 4px; transform-origin: left center; transform: perspective(420px) rotateY(calc(var(--open) * 62deg)); background: var(--surface-2); border-right: 1px solid var(--rule-strong); box-shadow: inset 0 0 0 1px var(--rule-strong); transition: transform .7s var(--fx-ease-io), background-color .3s ease; transition-delay: var(--d, 0ms); }
.dr__leaf::after { content: ""; position: absolute; right: 13px; top: 54%; width: 8px; height: 13px; background: radial-gradient(circle at 50% 3px, var(--ink-3) 2.6px, transparent 3px), linear-gradient(var(--ink-3), var(--ink-3)) 50% 100% / 3px 8px no-repeat; }
.dr.is-open { --open: 1; }
.dr.is-open .dr__frame { border-color: var(--os); box-shadow: 0 12px 22px -16px var(--os); }
.dr__stamp { position: absolute; z-index: 2; left: 50%; top: 8px; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 999px; background: var(--surface); border: 1px solid var(--rule-strong); font: 700 .58rem/1.3 var(--font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); white-space: nowrap; }
.dr__stamp svg { width: 10px; height: 10px; color: var(--os); }
.dr__name { margin: 0 !important; font: 700 .9rem/1.25 var(--font-body) !important; color: var(--ink); }
.dr__sub { margin: 0 !important; font-size: .78rem !important; line-height: 1.35; color: var(--ink-3); }
.dr__where { margin: 0 !important; font: 600 .72rem/1.3 var(--font-mono) !important; color: var(--os); min-height: 1.3em; }
.dr:not(.is-open) .dr__name { color: var(--ink-3); }
.dr:not(.is-open) .dr__where { color: var(--ink-3); }
.dr-out { margin: 18px 0 0 !important; font-size: 1rem !important; line-height: 1.5; min-height: 3em; }
@container fx (max-width: 719px) {
  .dr-wall { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 18px; }
  .dr__frame { height: 104px; }
}
@container fx (max-width: 400px) {
  .dr-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container fx (max-width: 560px) {
  .dm { stroke-width: 4.4; }
  .dr-label { font-size: 24px; }
}

/* Doors that do not exist in the chosen region are wall: a dashed outline, no leaf, no stamp. Most of the world:
   the two law-made doors are one blank stretch of wall, where Android's "unknown sources" switch would be.
   Each slot has a fixed cell, so the blank stretch can lie over the last two. */
.dr[data-door="store"] { grid-area: 1 / 1; } .dr[data-door="tf"] { grid-area: 1 / 2; } .dr[data-door="dev"] { grid-area: 1 / 3; }
.dr[data-door="ent"] { grid-area: 1 / 4; } .dr[data-door="mkt"] { grid-area: 1 / 5; } .dr[data-door="web"] { grid-area: 1 / 6; }

.dr.is-wall .dr__frame { border-style: dashed; border-color: var(--rule-strong); background: repeating-linear-gradient(0deg, transparent 0 17px, color-mix(in srgb, var(--rule-strong) 45%, transparent) 17px 18px); }
.dr.is-wall .dr__leaf { opacity: 0; }
.dr.is-wall .dr__stamp, .dr.is-wall .dr__sub { visibility: hidden; }
.dr-wall[data-r="world"] .dr.is-wall { display: none; }
.dr-blank { position: relative; z-index: 2; grid-row: 1; grid-column: 5 / span 2; align-self: start; margin: 0 !important; height: 128px; display: none; place-items: center; text-align: center; padding: 0 10px;
  border-radius: 10px; border: 2px dashed var(--rule-strong); background: repeating-linear-gradient(0deg, transparent 0 17px, color-mix(in srgb, var(--rule-strong) 40%, transparent) 17px 18px), repeating-linear-gradient(90deg, transparent 0 47px, color-mix(in srgb, var(--rule-strong) 25%, transparent) 47px 48px); }
.dr-wall[data-r="world"] .dr-blank { display: grid; }
.dr-blank span { padding: 6px 12px; border-radius: 999px; background: var(--surface); border: 1px dashed var(--rule-strong); font: 600 .8rem/1.3 var(--font-body); color: var(--ink-2); }
.dr-out:empty { display: none; }
@container fx (max-width: 719px) {
  .dr[data-door="ent"] { grid-area: 2 / 1; } .dr[data-door="mkt"] { grid-area: 2 / 2; } .dr[data-door="web"] { grid-area: 2 / 3; }
  .dr-blank { grid-row: 2; grid-column: 2 / span 2; height: 104px; }
}
@container fx (max-width: 400px) {
  .dr[data-door="dev"] { grid-area: 2 / 1; } .dr[data-door="ent"] { grid-area: 2 / 2; } .dr[data-door="mkt"] { grid-area: 3 / 1; } .dr[data-door="web"] { grid-area: 3 / 2; }
  .dr-blank { grid-row: 3; grid-column: 1 / span 2; }
}
.dr-map { max-width: 640px; margin-inline: auto; }

/* ======================= The purpose string: the camera prompt, by hand ======================= */
.ip-top { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: clamp(18px, 4cqi, 44px); align-items: center; }
.ip-phone { --w: clamp(220px, 30cqi, 280px); }
.ip-screen .fx-sb { color: #fff; }
.ip-screen.is-light .fx-sb { color: #1d1d27; }
.ip-screen.is-light .io-home-ind { background: rgba(29, 29, 39, .5); }
.ip-app { padding: 3em .9em 1em; background: #fffdf3; color: #1d1d27; display: flex; flex-direction: column; gap: .75em; transition: opacity .3s ease, transform .3s var(--fx-ease-out), filter .3s ease; }
.ip-app__title { margin: 0 !important; font: 700 1.25em/1.1 var(--font-body) !important; color: #1d1d27; }
.ip-app.is-dim { filter: brightness(.55) saturate(.8); }
.ip-app.is-crash { animation: ip-crash .32s var(--fx-ease-in) both; }
@keyframes ip-crash { 0% { transform: none; opacity: 1; } 35% { transform: scale(1.02); filter: brightness(1.4); } 100% { transform: scale(.6); opacity: 0; } }
.ip-note { display: grid; gap: .45em; padding: .7em 0 .2em; border-top: 1px solid #ece6cf; }
.ip-note i { display: block; height: .42em; border-radius: .3em; background: #e2dcc6; }
.ip-note i:nth-child(2) { width: 82%; } .ip-note i:nth-child(3) { width: 90%; } .ip-note i:nth-child(4) { width: 54%; }
.ip-take { all: unset; display: inline-flex; align-items: center; justify-content: center; gap: .45em; padding: .7em .8em; border-radius: .9em; background: #1d1d27; color: #fffdf3; font: 600 .95em/1.1 var(--font-body); cursor: pointer; box-shadow: 0 .35em .9em -.3em rgba(0, 0, 0, .45); transition: transform .16s var(--fx-ease-out); -webkit-tap-highlight-color: transparent; }
.ip-take svg { width: 1.35em; height: 1.35em; }
.ip-take:active { transform: scale(.96); }
.ip-take:focus-visible { outline: 2px solid #c7962b; outline-offset: 3px; }
.ip-take.is-refused { animation: fx-refuse .36s var(--fx-ease-out); }
.ip-result { position: relative; flex: 1; min-height: 4.6em; }
.ip-result[data-shown=""]::before { content: ""; position: absolute; inset: 0; border-radius: .7em; border: 1px dashed #e2dcc6; background: repeating-linear-gradient(135deg, transparent 0 .6em, rgba(226, 220, 198, .35) .6em .65em); }
.ip-view, .ip-nocam { position: absolute; inset: 0; opacity: 0; transition: opacity .3s ease; }
.ip-result[data-shown="cam"] .ip-view, .ip-result[data-shown="none"] .ip-nocam { opacity: 1; }
.ip-result:not([data-shown="none"]) .ip-nocam { visibility: hidden; }
.ip-view { border-radius: .7em; background: radial-gradient(70% 60% at 40% 35%, #3b4a5e, #11151f 75%); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); }
.ip-view::before { content: ""; position: absolute; inset: .7em; border: 1.5px solid rgba(255, 255, 255, .55); border-radius: .3em; -webkit-mask: linear-gradient(#000 0 0) top left / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) top right / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) bottom left / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) bottom right / 1.1em 1.1em no-repeat; mask: linear-gradient(#000 0 0) top left / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) top right / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) bottom left / 1.1em 1.1em no-repeat, linear-gradient(#000 0 0) bottom right / 1.1em 1.1em no-repeat; }
.ip-view i { position: absolute; left: 50%; bottom: .55em; width: 1.6em; height: 1.6em; margin-left: -.8em; border-radius: 50%; background: #fff; box-shadow: 0 0 0 .2em rgba(255, 255, 255, .35); }
.ip-nocam { margin: 0 !important; display: grid; place-items: center; text-align: center; padding: .6em; border-radius: .7em; border: 1px dashed #d8d0b4; font: 600 .82em/1.35 var(--font-body) !important; color: #6b6450; }

/* The system's dialog: a drawing of it, in iOS's look, with the student's own sentence inside. */
.ip-alert { display: grid; place-items: center; padding: 0 .7em; background: rgba(10, 10, 16, .28); z-index: 2; }
.ip-alert__box { width: 100%; border-radius: 1.1em; background: rgba(246, 245, 250, .97); color: #15151c; text-align: center; overflow: hidden; box-shadow: 0 1em 2.4em -1em rgba(0, 0, 0, .55); transform: scale(1.06); opacity: 0; transition: transform .28s var(--fx-ease-pop), opacity .2s ease; }
.ip-alert:not(.is-off) .ip-alert__box { transform: none; opacity: 1; }
.ip-alert__t { margin: 0 !important; padding: 1em .9em .3em; font: 700 .86em/1.25 var(--font-body) !important; color: #15151c; }
.ip-alert__m { margin: 0 !important; padding: 0 .9em .9em; font: 500 .78em/1.35 var(--font-body) !important; color: #2c2c36; overflow-wrap: anywhere; }
.ip-alert__b { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid rgba(60, 60, 67, .22); }
.ip-alert__b button { all: unset; padding: .8em .3em; font: 500 .84em/1.15 var(--font-body); color: #0a6cdf; text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.ip-alert__b button + button { border-left: 1px solid rgba(60, 60, 67, .22); font-weight: 700; }
.ip-alert__b button:focus-visible { outline: 2px solid #0a6cdf; outline-offset: -3px; border-radius: .4em; }
.ip-alert__b button:active { background: rgba(60, 60, 67, .1); }

.ip-side { display: grid; gap: 16px; min-width: 0; max-width: 520px; align-content: center; }
.ip-field { display: grid; gap: 6px; min-width: 0; }
.ip-field__k { font: 600 .74rem/1.3 var(--font-mono); color: var(--ink-2); letter-spacing: .02em; overflow-wrap: anywhere; }
.ip-str { width: 100%; min-height: 44px; padding: 9px 12px; border-radius: 10px; border: 1.5px solid var(--control); background: var(--surface); color: var(--ink); font: 500 .94rem/1.35 var(--font-body); transition: border-color .16s ease, opacity .16s ease; }
.ip-str:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent); }
.ip-str:disabled { opacity: .45; border-style: dashed; text-decoration: line-through; }
.ip-set { display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px; padding: 2px 12px; border-radius: 12px; background: var(--fx-plate); border: 1px solid var(--rule); }
.ip-set .fx-switch { font-weight: 600; font-size: .86rem; }
.ip-set .fx-switch input:disabled { opacity: .45; cursor: not-allowed; }
.ip-st { font: 600 .74rem/1.3 var(--font-mono); color: var(--ink-3); }
.ip-st[data-auth="on"] { color: var(--ok); }
.ip-st[data-auth="off"] { color: var(--no); }
.ip-reset { justify-self: start; }
@container fx (max-width: 719px) {
  .ip-top { grid-template-columns: minmax(0, 1fr); }
  .ip-phone { --w: min(64cqi, 240px); justify-self: center; }
  .ip-alert__b button { display: grid; place-items: center; min-height: 44px; padding-block: .2em; }
}

/* ---------- Wide figures: the phone on the left, everything that answers it on the right ----------
   The controls, the log and the lesson sit beside the phone, so a tap and what iOS did are on screen together, and the
   space under the controls is not empty (design review S9). Narrow figures keep the stacked layout above. */
@container fx (min-width: 720px) {
  .ip > .fx__stage, .io > .fx__stage { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: repeat(6, auto) 1fr; column-gap: clamp(18px, 4cqi, 44px); align-items: start; }
  .ip > .fx__stage > *, .io > .fx__stage > * { grid-column: 2; min-width: 0; }
  .ip > .fx__stage > .fx__kicker, .io > .fx__stage > .fx__kicker { grid-column: 1 / -1; }
  .ip-top, .io-top { display: contents; }
  .ip-phone, .io-phone { grid-column: 1; grid-row: 2 / -1; }
  .ip-side, .io-side { grid-column: 2; max-width: none; }
  .ip-side { margin-top: 6px; }
  /* Beside the phone, an empty line costs nothing in height: no reserved space under the controls. */
  .ip > .fx__stage > .fx-refuse:empty, .io > .fx__stage > :is(.fx-refuse, .io-caption):empty { min-height: 0; margin: 0 !important; }
}
@container fx (max-width: 460px) { .io-mem { grid-template-columns: minmax(0, 1fr); } }

/* ---------- Presentation mode: each simulator fits one slide ---------- */
[data-teaching="true"] .io-phone { --w: 168px; }
[data-teaching="true"] .ip-phone { --w: 190px; }
/* A smaller phone on the slide, so the dialog's words grow inside it: the class reads the student's sentence. */
[data-teaching="true"] .ip-alert__t { font-size: .98em !important; }
[data-teaching="true"] .ip-alert__m { font-size: .92em !important; }
[data-teaching="true"] .fx .fx__stage { padding: 16px 22px; }
[data-teaching="true"] .fx .fx-log { margin-top: 10px; padding: 10px 12px 6px; min-height: 48px; }
[data-teaching="true"] .fx .fx-lesson { min-height: 1.5em; margin-top: 8px !important; }
[data-teaching="true"] .fx :is(.fx-lesson, .fx-refuse, .io-caption):empty { display: none; }
[data-teaching="true"] .dr-wall { margin-top: 10px; padding-top: 26px; }
[data-teaching="true"] .fx .fx-seg > legend { margin-bottom: 4px; }
[data-teaching="true"] .dr__frame, [data-teaching="true"] .dr-blank { height: 80px; }
[data-teaching="true"] .dr-map { max-width: 480px; margin-inline: auto; margin-top: -8px; }
