/* The styles of the Projects pages of the console (console/projects/; v1.8.0, prompts/sprints/sprint-aso2.md, the
   contract's section 13). The approved look is docs/design/projects-mockup.src.html, variant A: a list of rows by
   state, a page of its own for a project, and the preset's field of New project. What the console has already
   (cards, badges, buttons, chips, fields) is console/app.css; this sheet adds what is new, in its manner.
   The page's policy admits no inline style: everything is a class of a sheet. */

/* --- What the console's own sheet lacks for these pages. This sheet is loaded with every page of the console, so
   a rule here that names no class of these pages is held to them: the project's page (`.proj`) and the search of
   the list (`.seek`). ------------------------------------------------------------------------------------------- */
.banner.accent { border-color: color-mix(in srgb, var(--accent) 30%, transparent); background: var(--accent-soft); }
.banner.quiet { border-color: var(--border); background: var(--surface-elev); color: var(--text-muted); }
.proj .banner b { font-weight: 500; }
.btn.danger.armed { background: var(--danger-soft); border-color: var(--danger); }
.proj .input::placeholder, .seek .input::placeholder { color: var(--text-faint); }
.proj .warn { color: var(--warning); }
.clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.one { display: block; width: 100%; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.i-image { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='14' height='12' rx='1.5'/%3E%3Ccircle cx='7.5' cy='8.5' r='1.25'/%3E%3Cpath d='M3.5 14.5l4-4 3 3 2-2 4 4'/%3E%3C/svg%3E"); }
.i-warn { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 3.5l7 12.5H3z'/%3E%3Cpath d='M10 8.5v3.5M10 14.2v.3'/%3E%3C/svg%3E"); }

/* --- The tools over the list: the groups with their counts, and the search --------------------------------------- */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.chip.count { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.chip .n { font-family: var(--font-mono); font-size: 11px; font-weight: 400; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.chip .n.bad { color: var(--danger); }
.chip[aria-pressed="true"] .n, .chip[aria-pressed="true"] .n.bad { color: inherit; }
.input.search { width: 220px; height: 32px; font-size: 13px; -webkit-appearance: none; appearance: none; }
/* A choice of the form that the choice above it does not take (a variant the pipeline does not make): faded. */
.chip:disabled { opacity: .45; cursor: not-allowed; border-style: dashed; }

/* --- A project's icon, where the white sheet stood ---------------------------------------------------------------- */
.gico { position: relative; width: 44px; height: 44px; flex: none; border-radius: 10px; overflow: hidden; background: var(--surface-elev); display: grid; place-items: center; color: var(--text-faint); }
.gico img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gico::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--hair); pointer-events: none; }
.gico.none { background: var(--bg); } .gico.none::after { box-shadow: inset 0 0 0 1px var(--border); }
.gico.lg { width: 64px; height: 64px; border-radius: 14px; }
.gico.xl { width: 96px; height: 96px; border-radius: 22px; }
.ring { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--text-muted); }
.gico.lg .ring, .gico.xl .ring { width: 20px; height: 20px; }

/* --- A project's row. A grid with fixed columns, so that the strips, the numbers and the badges of all rows stand
   in columns; the middle zone is 48 high whatever it holds, so that every row is as high. -------------------------- */
.listbox { container-type: inline-size; container-name: list; display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; min-width: 0; }
.pr:not([hidden]) ~ .pr { border-top: 1px solid var(--border); }
.prow { display: grid; grid-template-columns: 44px minmax(0, 1fr) 228px 82px 14px; column-gap: 12px; align-items: center; padding: 14px 24px; min-height: 76px; }
a.prow:focus-visible { box-shadow: inset var(--shadow-focus); border-radius: 0; }
.who { min-width: 0; }
.who .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.desc.meta { display: flex; align-items: baseline; }
.meta .mk { flex: none; white-space: pre; }
.meta .id { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-family: var(--font-mono); font-size: 11px; }
.zone { height: 48px; min-width: 0; display: flex; align-items: center; }
.strip { display: flex; gap: 2px; }
.th { position: relative; flex: none; width: 21px; height: 46px; border-radius: 3px; overflow: hidden; background: var(--surface-elev); }
.th img { display: block; width: 100%; height: 100%; object-fit: cover; }
.th::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--hair); pointer-events: none; }
.th.bare::after { box-shadow: inset 0 0 0 2px var(--warning); }
/* A lying game's ten: two rows of five, in the same room. */
.strip.lying { flex-wrap: wrap; width: 228px; }
.strip.lying .th { width: 44px; height: 20px; }
.zone.run { flex-direction: column; align-items: stretch; justify-content: center; gap: 9px; }
.runline { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-size: 12px; line-height: 1.2; white-space: nowrap; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.runline .sep { color: var(--text-faint); }
.runline .wk { margin-left: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 11px; color: var(--text-faint); }
.zone.why { font-size: 12px; line-height: 1.4; color: var(--text-muted); }
.zone.why.bad { color: var(--danger); } .zone.why.ask { color: var(--text); }
.state { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; }
.score { font-family: var(--font-mono); font-size: 12px; line-height: 1; font-variant-numeric: tabular-nums; }
.score i, .bigscore i { font-style: normal; color: var(--text-faint); }
/* Where the list is too narrow for one line, a row has two: the name with the state, and under them the zone, at
   its full width. Every row still has both lines, so the rows stay as high as each other. */
@container list (max-width: 688px) {
  .prow { grid-template-columns: 44px minmax(0, 1fr) auto 14px; grid-template-areas: "ico who state arrow" "zone zone zone zone"; row-gap: 12px; padding: 14px 16px; }
  .prow > .gico { grid-area: ico; } .prow > .who { grid-area: who; } .prow > .zone { grid-area: zone; }
  .prow > .state { grid-area: state; align-items: flex-end; } .prow > .arrow, .prow > .gap { grid-area: arrow; }
}

/* --- The skeleton of what is still loading, and how it gives way --------------------------------------------------- */
.sk { position: relative; overflow: hidden; background: var(--skel); }
.sk::after { box-shadow: none; }
.sk.ln { display: block; height: 10px; border-radius: 3px; }
.sk.ln.w1 { width: 46%; margin-top: 3px; } .sk.ln.w2 { width: 78%; height: 8px; margin-top: 10px; margin-bottom: 3px; }
.sk.pill { display: block; width: 52px; height: 16px; border-radius: var(--r-chip); }
/* A picture that is on its way: its node waits, unseen, and the block it stands in is the skeleton of its size.
   A picture that is not there (console/pictures.mjs: the orchestrator has none, or it could not be read) is unseen
   too, and its block is plain: nothing shimmers where nothing is on its way. */
img.wait, img.none { visibility: hidden; }
.th:has(> img.wait), .gico:has(> img.wait), .fr:has(> img.wait) { background: var(--skel); }
@keyframes shimmer { to { transform: translateX(100%); } }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: no-preference) {
  .seg.now { animation: breathe 2.4s ease-in-out infinite; }
  .ring { animation: spin 0.9s linear infinite; }
  .sk::before, .th:has(> img.wait)::before, .gico:has(> img.wait)::before, .fr:has(> img.wait)::before { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--shine), transparent); transform: translateX(-100%); animation: shimmer 1.9s ease-in-out infinite; }
  .fade { animation: fadein 360ms ease-out both; }
  img.in { animation: fadein 320ms ease-out both; }
}

/* --- The project's page -------------------------------------------------------------------------------------------- */
.proj { container-type: inline-size; container-name: proj; display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; min-width: 0; }
.proj > * { min-width: 0; }
.proj .card-body { grid-template-columns: minmax(0, 1fr); }
.proj .card-body > * { min-width: 0; }
.proj-head { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.proj-head .who { flex: 1 1 220px; }
.proj-head h1 { font-size: 18px; font-weight: 500; letter-spacing: -0.015em; line-height: 1.3; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.proj-head .desc { margin-top: 4px; }
.bigscore { font-family: var(--font-mono); font-size: 22px; font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums; }
.bigscore i { font-size: 13px; font-weight: 400; }
.grp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.slot { display: grid; gap: 10px; }
.slot .input { max-width: 420px; }
.slot .actions .input { flex: 1 1 220px; height: 32px; font-size: 13px; }
.setrow { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 20px; align-items: start; }
.setside { display: grid; gap: 16px; }
.cap { display: block; margin-top: 6px; font: 11px/1.45 var(--font-mono); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cap b { display: block; font-weight: 400; color: var(--text); }
.shots { display: flex; gap: 12px; overflow-x: auto; padding: 2px 2px 12px; scrollbar-width: thin; }
.shot { flex: 0 0 150px; margin: 0; display: grid; gap: 8px; align-content: start; }
.fr { position: relative; display: block; width: 100%; aspect-ratio: 360 / 783; border-radius: var(--r-card); overflow: hidden; background: var(--surface-elev); }
.fr.sk { background: var(--skel); }
.fr img { display: block; width: 100%; height: 100%; object-fit: cover; }
.fr::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--hair); pointer-events: none; }
.shots.lying .shot { flex-basis: 300px; }
.shots.lying .fr { aspect-ratio: 783 / 360; }
/* v1.12.0: a finished game's gameplay video on its page, at most as tall as a screen of the store set strip. */
.gvideo { display: block; max-width: 100%; max-height: 520px; border-radius: 10px; background: #000; }
/* The pictures of a stop (v1.9.0, console/projects/review.mjs): a frame that keeps a picture's own shape. Art and a
   lying screen would be cut to a sliver by the phone's shape: here every frame is as high as the others and as wide
   as its picture, which is shown whole. */
.shots.free .shot { flex: none; }
.fr.free { width: auto; min-width: 72px; height: 260px; aspect-ratio: auto; }
.fr.free img { width: auto; max-width: 420px; object-fit: contain; }
.shot.bare .fr::after { box-shadow: inset 0 0 0 2px var(--warning); }
.wmark { position: absolute; top: 8px; left: 8px; z-index: 1; width: 24px; height: 24px; border-radius: var(--r-chip); background: var(--warning-soft); color: var(--warning); display: grid; place-items: center; }
.wmark .ico { width: 15px; height: 15px; }
.shot figcaption { font: 11px/1.45 var(--font-mono); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.shot figcaption span { display: block; font-family: var(--font-sans); }
.shot .wnote { color: var(--warning); } .shot .later { color: var(--text-faint); }
.kv { margin: 0; display: grid; }
.kv > div { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 16px; padding: 10px 24px; font-size: 13px; }
.kv > div + div { border-top: 1px solid var(--border-subtle); }
.kv dt { font-size: 12px; color: var(--text-muted); line-height: 1.65; } .kv dd { margin: 0; overflow-wrap: anywhere; white-space: pre-line; }
.kv.in > div { padding-inline: 0; } .kv.in { border-top: 1px solid var(--border-subtle); }
.card > .kv { padding: 6px 0 10px; }
.segs { display: flex; gap: 3px; }
.seg { flex: 1; height: 6px; border-radius: 2px; background: var(--surface-elev); }
.seg.done, .seg.now { background: var(--accent); } .seg.fail { background: var(--danger); }
.steps { list-style: none; margin: 0; padding: 0; columns: 4 124px; column-gap: 28px; }
.steps li { break-inside: avoid; display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 8px; align-items: baseline; padding: 3px 0; font: 12px/1.5 var(--font-mono); font-variant-numeric: tabular-nums; }
.steps .n { font-size: 10px; color: var(--text-faint); }
.steps .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.steps .d { text-align: right; color: var(--text-muted); }
.steps li.todo { color: var(--text-faint); }
.steps li.now .nm, .steps li.now .d { color: var(--accent); font-weight: 500; }
.steps li.fail .nm, .steps li.fail .d { color: var(--danger); font-weight: 500; }
.delrow .actions { flex: none; }
@container proj (max-width: 560px) {
  .setrow { grid-template-columns: minmax(0, 1fr); }
  .setside { display: flex; align-items: flex-start; gap: 16px; }
  .kv > div { grid-template-columns: 88px minmax(0, 1fr); gap: 12px; padding-inline: 16px; }
  .kv.in > div { padding-inline: 0; }
}

/* --- New project: the preset of the store set, and its ten small pictures ------------------------------------------- */
.input.pick { max-width: 320px; }
.pthumbs { display: flex; gap: 6px; overflow-x: auto; padding: 2px 2px 8px; scrollbar-width: thin; min-height: 106px; align-items: flex-start; }
.pthumbs .th { width: 44px; height: 96px; border-radius: 5px; }
/* The screenshots of a game that lies, lying. */
.pthumbs.lying .th { width: 96px; height: 44px; }
/* The form asks for as many pictures as the preset's newest game has. One the orchestrator has not all the same
   (its archive went since the list was read) takes no room among them. */
.pthumbs .th:has(> img.none) { display: none; }
.pthumbs .xs { align-self: center; }
/* A preset no game was made under yet: its screens as blocks, each named for what stands on it. */
.th.shape { display: grid; place-items: center; }
.th.shape span { writing-mode: vertical-rl; font: 9px/1 var(--font-mono); color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.08em; }

/* --- New project, v1.14.0: the slider of how close a game is to its reference, its four stops named under it, and
   the pictures of the reference, each with the button that takes it out. -------------------------------------------- */
.stops { display: grid; gap: 4px; max-width: 420px; }
.stops input[type="range"] { width: 100%; margin: 0; accent-color: var(--accent); }
.stops .marks { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-faint); }
.stops .marks .on { color: var(--accent); font-weight: 500; }
.refpics { display: flex; flex-wrap: wrap; gap: 10px; }
.refpic { display: grid; gap: 4px; justify-items: start; }
.refpic img { display: block; width: 72px; height: 72px; object-fit: cover; border-radius: 5px; border: 1px solid var(--border); background: var(--surface-elev); }

@media (max-width: 800px) {
  .toolbar .input.search { width: 100%; }
  .toolbar > .seek { flex: 1 1 100%; }
}

/* --- s18-AC, the result of a game and the Quality view (v1.9.0): begin */
/* A score under the judge's bar, in a row of the list, in the head of a project's page and in a table. */
.score.low, .bigscore.low, .table td.low { color: var(--warning); }
/* The result block: the score line, then a row a screenshot: the picture the judge's rules point at, and beside it
   those rules, each with what became of it and what the judge said in its two answers. A screenshot is shown
   whole, whichever way the game lies; one the orchestrator has not takes no room. A rule is a fold: one that
   passed is closed to its name. */
.resline { margin: 0; font-size: 14px; }
.resline.low { color: var(--warning); }
.crit { list-style: none; margin: 0; padding: 0; display: grid; }
.critrow { display: flex; align-items: flex-start; gap: 14px; padding: 12px 0; min-width: 0; }
.critrow + .critrow { border-top: 1px solid var(--border-subtle); }
.critrow .th { width: 81px; height: 144px; border-radius: var(--r-input); }
.critrow .th img { object-fit: contain; }
.critrow .th:has(> img.none) { display: none; }
.critrow .grow { display: grid; gap: 4px; min-width: 0; }
.shotname { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); overflow-wrap: anywhere; }
.rule { min-width: 0; }
.rule > .title { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 3px 0; font-family: var(--font-mono); font-size: 12px; cursor: pointer; }
.said { margin: 2px 0 4px 14px; font-size: 13px; color: var(--text-muted); overflow-wrap: anywhere; }
.ans { margin-right: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
/* The Quality view: the four colours of an app's design, side by side. */
.swatches { display: inline-flex; gap: 4px; vertical-align: middle; }
.swatch { width: 18px; height: 18px; border-radius: var(--r-chip); box-shadow: inset 0 0 0 1px var(--hair); }
/* --- s18-AC: end */
