/* ══════════════════════════════════════════════════════════════════════
   css/photo-stage.css — the PHOTO STAGE, as a component

   The website's Photos step, which Alex holds up as the layout standard for
   anything with a preview in it: a strip of what you are changing across the
   top, the preview in the middle with the device toggle sitting ON it, and the
   options in a rail beside it — so the controls surround the workspace instead
   of being stranded in a bottom bar you have to scroll to.

   Alex, 2026-08-02: "even the way that the preview sits, the ability to swap
   between mobile and desktop, and having the option surrounding that workspace
   so you're not moving around and you're not scrolling down the bottom bar. We
   should be completely replicating our website site UX."

   Every rule was scoped to `#page-launch-photos`, so the course Look step could
   not wear it. Same extraction, same risk, same proof as review-canvas.css:
   an id selector becomes a class one, specificity drops (1,1,0) → (0,2,0), and
   tests/browser/photo-stage-css.browser.js renders the website's own markup
   before and after to show nothing moved. The host must opt in with `pho`.
   ══════════════════════════════════════════════════════════════════════ */


.pho .pho-ph { position: relative; background: repeating-linear-gradient(135deg, #efece2, #efece2 9px, #e7e3d6 9px, #e7e3d6 18px); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.pho .pho-ph .lab { font-family: "JetBrains Mono", monospace; font-size: 11px; letter-spacing: 0.04em; color: #97917f; background: rgba(255,255,255,0.78); padding: 5px 11px; border-radius: 7px; border: 1px solid rgba(0,0,0,0.05); text-align: center; max-width: 80%; }

.pho .pho-strip { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px 16px; margin-bottom: 14px; display: flex; align-items: center; gap: 14px; }
.pho .pho-strip .l { font-family: "JetBrains Mono", monospace; font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); flex-shrink: 0; }
.pho .pho-track { flex: 1; display: flex; gap: 6px; overflow-x: auto; padding: 2px; }
.pho .pho-track::-webkit-scrollbar { height: 4px; }
.pho .pho-track::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 2px; }
.pho .pho-thumb { flex-shrink: 0; width: 52px; height: 42px; border-radius: 7px; border: 1.5px solid var(--border); cursor: pointer; position: relative; overflow: hidden; background: var(--surface-3); }
.pho .pho-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pho .pho-thumb.done::after { content: ""; position: absolute; top: 3px; right: 3px; width: 15px; height: 15px; border-radius: 50%; background: var(--good); border: 1.5px solid #fff; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='4'><path d='M5 12l5 5L20 7'/></svg>"); background-repeat: no-repeat; background-position: center; background-size: 9px; }
.pho .pho-thumb.on { border-color: var(--accent); border-width: 2px; box-shadow: 0 0 0 3px var(--accent-soft); }
.pho .pho-counter { font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 13px; flex-shrink: 0; }
.pho .pho-counter b { color: var(--accent); }

.pho .pho-stage { display: grid; grid-template-columns: minmax(0,1fr) 350px; gap: 16px; align-items: start; }
.pho .pho-main { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; display: flex; flex-direction: column; }
.pho .pho-ctx { padding: 12px 18px; border-bottom: 1px solid var(--border-soft); background: var(--surface-2); display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pho .pho-ctx .where { display: flex; align-items: center; gap: 11px; }
.pho .pho-ctx .badge { background: var(--accent-soft); color: var(--accent-deep); padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; font-family: "JetBrains Mono", monospace; letter-spacing: 0.04em; }
.pho .pho-ctx .where b { font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 14.5px; }
.pho .pho-ctx .where .s { font-size: 11.5px; color: var(--text-3); margin-top: 1px; }
.pho .pho-ctx .ctx-right { display: flex; align-items: center; gap: 10px; }
.pho .pho-ctx .arrows { display: flex; gap: 4px; }
.pho .pho-ctx .arrows button { width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); color: var(--text-2); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.pho .pho-ctx .arrows button:hover { background: var(--surface-2); color: var(--text); }
.pho .pho-ctx .arrows svg { width: 14px; height: 14px; }
.pho .pho-canvas { flex: 1; padding: 28px; display: flex; align-items: center; justify-content: center; min-height: 420px; background: var(--surface-3); }
.pho .pho-big { width: 100%; aspect-ratio: 16/10; border-radius: 12px; box-shadow: 0 18px 48px -18px rgba(0,0,0,0.3); overflow: hidden; background: var(--surface); }
.pho .pho-big img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pho .pho-big .lab { font-size: 13px; }
/* The action bar sits ABOVE the page now — the job reads before the picture.
   Decision state (.pho-meta) and save state (.pho-pagebar) swap; never both. */
/* BOTH STATES, ONE HEIGHT. The decision row and the save strip swap in the
   same slot, and when their heights differed the whole canvas below jumped
   49px on every save — which read, convincingly, as the photo moving. The
   harness proved the crop pixel-identical once re-aligned: the page was the
   thing that moved. Same fixed height, no jump, nothing below ever shifts. */
.pho .pho-meta { min-height: 62px; height: 62px; overflow: hidden; box-sizing: border-box; padding: 10px 16px; border: 1px solid var(--border-soft); border-radius: 12px; display: flex; align-items: center; justify-content: space-between; gap: 14px; background: var(--surface); }
.pho .pho-meta[hidden] { display: none; }
.pho .pho-meta .t { font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 16px; }
.pho .pho-meta .sub { font-size: 12px; color: var(--text-3); margin-top: 1px; }
.pho .pho-meta .acts { display: flex; gap: 8px; }
.pho .pho-meta .acts .btn { padding: 9px 15px; font-size: 13px; }

.pho .pho-rail { display: flex; flex-direction: column; gap: 12px; }
.pho .pho-rcard { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.pho .pho-tabs { display: flex; gap: 4px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 9px; padding: 3px; margin-bottom: 12px; }
.pho .pho-tabs button { flex: 1; border: none; background: transparent; padding: 7px 6px; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--text-3); font-family: "Inter", sans-serif; cursor: pointer; }
.pho .pho-tabs button.on { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
/* ⚠️ BIG ENOUGH TO JUDGE. Alex, 2026-08-03: "In a very detailed image like
   this one, I have no idea what is actually happening in the image."

   Two columns inside a ~340px rail is a ~160px tile — a thumbnail of a
   thumbnail. `minmax(150px, 1fr)` keeps two columns in the rail but lets the
   same grid open out wherever the panel is wider, and 4/3 shows more of a
   landscape photograph than a square crop of its middle did. */
/* ⚠️ FOUR ACROSS, FIXED — Alex, 2026-08-06: *"It might be also better to show
   smaller images instead of such big ones so they can see more images at the
   same time… We might have four so it's kind of a better layout."*

   This was `auto-fill, minmax(150px, 1fr)`, which on the wizard's ~340px rail
   resolves to TWO columns of ~165px — the "such big ones" he means. Four is
   asked for by name, and fixed rather than derived so the answer is the same
   on the rail and on the wide photo stage: auto-fill would have kept growing
   the column count on a wide panel and shrunk the tiles past useful.

   ⚠️ AND IT IS A REVERSAL WORTH KNOWING ABOUT. On 2026-08-03 he said the
   opposite — *"In a very detailed image like this one, I have no idea what is
   actually happening in the image"* — and the tiles were made BIGGER for it.
   What changed in between is that the tiles were being drawn from a 130px
   source (see `urls` in photo-picker.js), so "bigger" meant "more blur, less
   choice". With the source fixed, four sharp tiles beat two soft ones. If it
   turns out to be too small to judge from, the fix is the magnifier
   launch-studio already has (`.pho-peek`), not a return to two. */
.pho .pho-sugg { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }

/* The picture they have ALREADY chosen, at the top, at full panel width —
   the picker used to open with no sign of what it was about to replace. */
.pho .pho-current {
  margin-bottom: 10px; border-radius: 10px; overflow: hidden;
  border: 1.5px solid var(--accent); background: var(--surface-3);
}
.pho .pho-current img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; }

.pho .pho-more-wrap { margin-top: 10px; text-align: center; }
.pho .pho-more {
  background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
  padding: 8px 16px; font-family: inherit; font-size: 13px; color: var(--text-2);
  cursor: pointer; min-height: 36px;
}
.pho .pho-more:hover { border-color: var(--accent); color: var(--text); }
.pho .pho-more[disabled] { opacity: .6; cursor: default; }
.pho .pho-sg { aspect-ratio: 4/3; border-radius: 10px; border: 1.5px solid var(--border); cursor: pointer; transition: transform .12s, border-color .12s; overflow: hidden; background: var(--surface-3); }
.pho .pho-sg:hover { transform: translateY(-2px); border-color: var(--accent); }
.pho .pho-sg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pho .pho-searchbar { display: flex; gap: 6px; margin-bottom: 10px; }
.pho .pho-searchbar input { flex: 1; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font-family: inherit; font-size: 13px; color: var(--text); outline: none; }
.pho .pho-searchbar input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.pho .pho-searchbar button { background: var(--accent); color: #fff; border: none; border-radius: 8px; padding: 8px 13px; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.pho .pho-loading { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 22px; color: var(--text-3); font-size: 12.5px; }
.pho .pho-loading .sp { width: 20px; height: 20px; border: 2.5px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: ls-spin .8s linear infinite; }
.pho .pho-empty { grid-column: 1 / -1; text-align: center; color: var(--text-3); font-size: 12.5px; padding: 22px; }
/* Under the suggested grid: what the photos were searched for, and the other
   angles the model offered — so one poor guess is not a dead end. */
.pho .pho-sugg-foot { margin-top: 10px; }
.pho .pho-sugg-why { color: var(--text-3); font-size: 12px; margin-bottom: 6px; }
.pho .pho-sugg-alts { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; color: var(--text-3); font-size: 12px; }
.pho .pho-alt { background: var(--surface-3); border: 1px solid var(--border); border-radius: 999px; padding: 5px 11px; font-size: 12px; font-family: inherit; color: var(--text-2); cursor: pointer; }
.pho .pho-alt:hover { border-color: var(--accent); color: var(--text); }
.pho .pho-upl { margin-top: 12px; }
.pho .pho-upl .btn { width: 100%; justify-content: center; padding: 11px; font-size: 13px; }
.pho .pho-from { display: flex; flex-wrap: wrap; gap: 7px; }
.pho .pho-from .c { display: inline-flex; align-items: center; gap: 7px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2); border-radius: 9px; padding: 8px 11px; font-size: 12.5px; font-weight: 500; cursor: pointer; }
.pho .pho-from .c:hover { border-color: var(--accent-2, var(--accent)); color: var(--accent-deep); background: var(--accent-softer, var(--accent-soft)); }
.pho .pho-from .c svg { width: 14px; height: 14px; }

.pho .pho-foot { position: sticky; bottom: 14px; margin-top: 16px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: 0 24px 50px -28px rgba(21,23,43,0.5); padding: 14px 20px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.pho .pho-foot .l { font-size: 13px; color: var(--text-3); display: flex; align-items: center; gap: 10px; }
.pho .pho-foot .l svg { width: 16px; height: 16px; color: var(--accent); }
.pho .pho-foot .l b { color: var(--text); font-weight: 600; }
.pho .pho-foot .actions { display: flex; gap: 10px; align-items: center; }

/* ── Photos: the page-grouped rail and the in-place viewer ─────────────────
   The flat strip is replaced by a rail grouped by page, and the lone <img> by
   the coach's own page at desktop width with the chosen photo lit up. Both
   exist to answer one question: which image am I changing, and where is it? */
.pho .pho-stage3 { grid-template-columns: 260px minmax(0,1fr) 330px; }
.pho .pho-pages { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; position: sticky; top: 12px; max-height: calc(100vh - 120px); display: flex; flex-direction: column; }
.pho .pho-pagesh { display: flex; align-items: center; justify-content: space-between; padding: 11px 13px; border-bottom: 1px solid var(--line); }
.pho .pho-pagesh .l { font-family: "JetBrains Mono", monospace; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); }
.pho .pho-pageslist { overflow-y: auto; padding: 6px; }
.pho .pho-pgh { display: flex; justify-content: space-between; align-items: baseline; padding: 10px 7px 5px; font-size: 12px; }
.pho .pho-pgh b { color: var(--text); font-weight: 600; }
.pho .pho-pgh span { font-size: 10.5px; color: var(--text-3); font-family: "JetBrains Mono", monospace; }
.pho .pho-prow { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; padding: 5px 7px; border: 0; background: none; border-radius: 8px; cursor: pointer; }
.pho .pho-prow:hover { background: var(--surface-2); }
.pho .pho-prow.on { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.pho .pho-prow .th { flex-shrink: 0; width: 40px; height: 32px; border-radius: 5px; overflow: hidden; background: var(--surface-3); position: relative; }
.pho .pho-prow .th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pho .pho-prow.done .th::after { content: "✓"; position: absolute; inset: 0; display: grid; place-items: center; background: rgba(22,163,74,.82); color: #fff; font-size: 13px; font-weight: 700; }
.pho .pho-prow .tx { min-width: 0; display: block; }
.pho .pho-prow .tx b { display: block; font-size: 12px; font-weight: 500; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pho .pho-prow.on .tx b { color: var(--text); font-weight: 600; }
.pho .pho-prow .tx i { display: block; font-style: normal; font-size: 10.5px; color: var(--warn); }

.pho .pho-viewtabs { display: flex; align-items: center; gap: 3px; }
.pho .pho-viewtabs button { border: 0; background: none; font: inherit; font-size: 11.5px; color: var(--text-3); padding: 4px 9px; border-radius: 999px; cursor: pointer; }
.pho .pho-viewtabs button:hover { color: var(--text); }
.pho .pho-viewtabs button.on { background: var(--surface-3); color: var(--text); font-weight: 500; }
.pho .pho-viewtabs .sep { width: 1px; height: 16px; background: var(--border); margin: 0 5px; }
/* A REAL height. Scaling the frame against a container that had none was why
   the page came out as a sliver at the top of a field of white. */
.pho .pho-canvas { position: relative; }
.pho .pho-page { position: relative; width: 100%; height: min(64vh, 600px); overflow: hidden; background: var(--surface-2); border-radius: 10px; }
.pho .pho-wtoggle { position: absolute; right: 12px; bottom: 12px; display: flex; gap: 2px; background: rgba(17,24,39,.72); backdrop-filter: blur(6px); border-radius: 999px; padding: 3px; }
.pho .pho-wtoggle button { border: 0; background: none; font: inherit; font-size: 11px; color: rgba(255,255,255,.7); padding: 4px 11px; border-radius: 999px; cursor: pointer; }
.pho .pho-wtoggle button.on { background: #fff; color: var(--text); font-weight: 500; }
/* The frame renders at a real laptop width and is scaled down, so the layout
   the coach sees is the layout their visitors get. */
.pho .pho-page { display: grid; place-items: center; padding: 12px; }
/* The device shell. A phone framed as a phone reads instantly; a mobile layout
   stretched across the whole panel just looks broken. */
.pho .pho-device { position: relative; overflow: hidden; background: #fff; border-radius: 10px; box-shadow: 0 8px 30px rgba(17,24,39,.16); }
/* No phone bezel. It was decoration that had to be sized in JS, and getting
   that wrong is what made the mobile view sit off-centre. A white page on the
   panel background reads as a phone perfectly well, and centres by itself. */
.pho .pho-page.is-mobile .pho-device { border-radius: 14px; }
.pho .pho-page iframe { border: 0; display: block; transform-origin: 0 0; background: #fff; }
.pho .pho-page[hidden], .pho .pho-big[hidden] { display: none; }
.pho .pho-loading { padding: 40px; text-align: center; color: var(--text-3); font-size: 13px; line-height: 1.9; }
.pho .pho-loading small { color: var(--warn); font-size: 11.5px; }
.pho .pho-loading button { margin-top: 10px; }
/* The photo says it can be dragged. */
.pho .pho-page iframe { cursor: default; }

/* §CERT-PREVIEW.2 — the certificates screen's middle box wears the
   CERTIFICATE's own shape. The PDF is drawn at 1122×793 (A4 landscape,
   course-certificate-service _htmlToPdf), so the box carries that exact
   ratio; the max-width leg keeps the ratio honest when the height cap
   would otherwise win and letterbox it. */
.pho .pho-page.pho-cert { height: auto; aspect-ratio: 1122 / 793; max-height: min(64vh, 600px); max-width: calc(min(64vh, 600px) * 1.4149); margin: 0 auto; }

.pho .pho-pagebar { min-height: 62px; height: 62px; box-sizing: border-box; display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; margin: 0 0 10px; padding: 10px 12px; background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); border-radius: 12px; overflow: hidden; }
.pho .pho-pagebar .n { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.pho .pho-pagebar .btn { flex: none; white-space: nowrap; padding: 8px 12px; font-size: 12.5px; }
.pho .pho-pagebar[hidden] { display: none; }
.pho .pho-pagebar .n { flex: 1; font-size: 12.5px; color: var(--text-2); font-weight: 500; }
/* An unsaved row reads as unsaved at a glance, not as done. */
.pho .pho-prow.unsaved .th { box-shadow: 0 0 0 2px var(--accent); }
.pho .pho-prow.unsaved .tx b::after { content: " \2022 unsaved"; color: var(--accent); font-weight: 600; }
/* The bar under the stage was sitting right on top of the footer actions. */
.pho .pho-foot { margin-top: 22px; }
.pho .pho-meta { margin: 0 0 10px; }
@media (max-width: 1080px) { .pho .pho-stage, .pho .pho-stage3 { grid-template-columns: 1fr; }
  .pho .pho-pages { position: static; max-height: 300px; }
}

@media (max-width: 760px) { .pho .pho-foot { flex-direction: column; align-items: stretch; }
}


/* ── The magnifier on picker tiles: inspect without choosing ── */
.pho .pho-sg { position: relative; }
.pho .pho-peek { position: absolute; right: 6px; bottom: 6px; width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center; border: 0; border-radius: 999px;
  background: rgba(20,16,50,.55); color: #fff; cursor: zoom-in; opacity: 0; transition: opacity .12s; }
.pho .pho-sg:hover .pho-peek { opacity: 1; }

/* ── One photo, two screens: the rail row carries a desktop thumb and a
   mobile thumb, each with its own tick; the row goes green when both are
   decided. Clicking a thumb jumps to that photo on that screen. ── */
/* The base .th rule fixes a 40px window with overflow hidden — wide enough
   for one thumb, which silently cropped the mobile one out of existence. The
   pair needs its own footprint. */
.pho .pho-prow .th.two { display: flex; gap: 4px; width: auto; height: auto; overflow: visible; background: none; }
.pho .pho-prow .th.two .vp { position: relative; width: 34px; height: 34px;
  border-radius: 8px; overflow: hidden; border: 1.5px solid var(--line); cursor: pointer; flex: none; display: block; }
.pho .pho-prow .th.two .vp img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pho .pho-prow .th.two .vp.cur { border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent); }
.pho .pho-prow .th.two .vp .dev { position: absolute; top: 2px; left: 2px;
  width: 13px; height: 13px; border-radius: 4px; background: rgba(20,16,50,.55);
  display: flex; align-items: center; justify-content: center; }
.pho .pho-prow .th.two .vp .tick { position: absolute; right: 2px; bottom: 2px;
  width: 13px; height: 13px; border-radius: 999px; background: #16a34a;
  display: none; align-items: center; justify-content: center; }
.pho .pho-prow .th.two .vp.ok .tick { display: flex; }