/* ==========================================================================
   Kanga’s Kitchen — how-to guides

   The editor is deliberately plain: the same cards, fields and one-per-line
   textareas the recipe editor uses, in the order you'd fill them in. The only
   thing here with any real design in it is a step — a numbered card with a
   handle on it — because a step is the thing she'll touch a hundred times.

   Only the theme tokens from styles.css are used, so dark mode comes for free.
   The one exception is the lightbox scrim, which is deliberately dark in both.
   ========================================================================== */

/* ── The editor ────────────────────────────────────────────────────────── */

.gedit__head { margin-bottom: 1.75rem; }
.gedit__head .lede { max-width: 46ch; }

.gedit__h2 {
  font-family: var(--serif); font-size: 1.35rem; font-weight: 600;
  margin: 0 0 .35rem;
}
.gedit__h2 + .hint { margin-top: 0; margin-bottom: 1rem; }

.gedit__addrow { margin: 1rem 0 0; }

.gedit__busy {
  display: flex; align-items: center; gap: .75rem;
  color: var(--ink-soft); padding: 1.5rem 0;
}
/* The shared spinner is sized for the middle of a busy card; inline beside a
   line of text it needs to be small, and a span needs telling to take a size. */
.gedit__busy .spinner { display: block; flex: none; width: 1.6rem; height: 1.6rem; border-width: 2px; margin: 0; }

.gedit__actions {
  display: flex; gap: .75rem; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--rule); padding-top: 1.5rem; margin-top: 2rem;
}
.gedit__actions .alert { flex-basis: 100%; margin: 0; }
.gedit__who { margin: 0 0 0 auto; }

/* ── The picture of the finished thing ─────────────────────────────────── */

.gdrop {
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: 2rem 1rem; text-align: center; color: var(--ink-soft);
  background: var(--paper); border: 2px dashed var(--rule); border-radius: var(--radius);
}
.gdrop strong { font-size: 1.05rem; color: var(--ink); }
.gdrop.is-over { border-color: var(--accent); background: var(--accent-wash); color: var(--accent-deep); }
.gdrop__row { display: flex; gap: .6rem; flex-wrap: wrap; justify-content: center; }

.ghero { display: flex; flex-direction: column; gap: .75rem; padding: 2px; border-radius: var(--radius); }
.ghero.is-over { outline: 2px dashed var(--accent); outline-offset: 2px; }
.ghero img {
  width: 100%; max-height: 320px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--rule); display: block;
}
.ghero__tools { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ── Which recipes it's for ────────────────────────────────────────────── */

/*
 * The chosen recipes stay here as chips. Choosing them happens in a full-screen
 * sheet of the recipe cards themselves, further down — the same grid, the same
 * blue check, the same floating count bar as "Select pages…" on the home
 * screen, because it is meant to be the same gesture and not a near-miss of it.
 */

.grec-chips { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.grec-chips:not(:empty) { margin-bottom: 1rem; }
.grec-chips__none { margin: 0; }

.grec-chip {
  display: inline-flex; align-items: center; gap: .5rem; max-width: 100%;
  padding: .25rem .25rem .25rem .3rem;
  background: var(--paper-deep); border: 1px solid var(--rule); border-radius: 999px;
  font-size: .9rem;
}
.grec-chip img, .grec-chip__blank {
  width: 34px; height: 34px; flex: none; border-radius: 999px;
  object-fit: cover; display: grid; place-items: center;
  background: var(--card); font-size: 1rem;
}
.grec-chip__name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grec-chip__x {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center; cursor: pointer;
  border: 0; border-radius: 999px; background: transparent; color: var(--ink-faint);
  -webkit-tap-highlight-color: transparent;
}
.grec-chip__x:hover { background: var(--danger-wash); color: var(--danger); }
.grec-chip__x:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }

/* ── Choosing them: the sheet ──────────────────────────────────────────── */

/* Full screen rather than a dialog in the middle of one. The cards are the
   controls, so they want the whole tablet — and half a screen of recipe cards
   inside a floating box reads as a menu, which is the thing being replaced. */
.grec-sheet {
  position: fixed; inset: 0; z-index: 300;
  display: flex; flex-direction: column;
  background: var(--paper);
}
.grec-sheet:focus { outline: none; }        /* it takes focus on open, silently */

.grec-sheet__head {
  display: flex; align-items: flex-end; gap: .75rem 1.5rem; flex-wrap: wrap;
  background: var(--card); border-bottom: 1px solid var(--rule);
  padding:
    max(1rem, env(safe-area-inset-top))
    max(1.25rem, env(safe-area-inset-right))
    1rem
    max(1.25rem, env(safe-area-inset-left));
}
.grec-sheet__intro { flex: 1 1 18rem; }
.grec-sheet__intro .gedit__h2 { margin-bottom: .2rem; }
.grec-sheet__intro .hint { margin: 0; }
.grec-sheet__search { flex: 1 1 20rem; max-width: 34rem; }

.grec-sheet__body {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding:
    1.25rem
    max(1.25rem, env(safe-area-inset-right))
    /* The last row has to clear the floating count bar — Done lives on it. */
    max(8rem, calc(env(safe-area-inset-bottom) + 7.5rem))
    max(1.25rem, env(safe-area-inset-left));
}
.grec-sheet__more { margin-top: 1.5rem; }
.grec-sheet__more .gedit__busy { justify-content: center; padding: 0; }

/* The card is the shelf's `.rcard`, but a <button> instead of an <a>. That buys
   the toggle for free — aria-pressed, the space bar, a focus ring — at the cost
   of having to undo a button's own type and centring, and of its innards being
   spans, which want telling that they are blocks. The blank tile keeps its grid
   so the pot emoji stays centred. */
.grec-sheet .rcard {
  display: flex; flex-direction: column; align-items: stretch;
  font: inherit; text-align: left; padding: 0;
  cursor: pointer; -webkit-appearance: none; appearance: none;
}
.grec-sheet .rcard__img:not(.rcard__img--blank) { display: block; }
.grec-sheet .rcard__title { display: block; }
/* A picked card already wears an accent outline, so the focus ring has to be a
   visibly different thing rather than the same ring in the same place. */
.grec-sheet .rcard:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }

/* Nothing behind the sheet should move while it's open. */
body.grec-open { overflow: hidden; }

/* ── The steps ─────────────────────────────────────────────────────────── */

.gsteps-block { margin: 2rem 0; }
.gsteps { list-style: none; padding: 0; margin: 0 0 1rem; display: grid; gap: .85rem; }

/* A quiet inset on the white page, not another sheet of paper on top of it —
   the editor sits on `.gedit` now, and card-on-card was card-coloured on
   card-coloured, with only a hairline saying where one step ended. */
.gstep {
  position: relative;
  background: var(--paper-deep); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: .75rem .9rem .9rem;
}
.gstep.is-over { border-color: var(--accent); background: var(--accent-wash); }

/* Lifted off the page and following the finger. It must never transition —
   a transition on the dragged card makes it lag behind the touch. */
.gstep.is-dragging {
  z-index: 5; box-shadow: var(--shadow-lg); border-color: var(--accent);
  transition: none;
}
/* Everything else slides out of the way, but only while a drag is running. */
.gsteps.is-reordering { user-select: none; -webkit-user-select: none; }
.gsteps.is-reordering .gstep { transition: transform .14s ease; }
.gsteps.is-reordering .gstep.is-dragging { transition: none; }

.gstep__bar { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .6rem; }
.gstep__gap { flex: 1 1 auto; }

.gstep__n {
  display: grid; place-items: center; flex: none;
  width: 2rem; height: 2rem; border-radius: 999px;
  background: var(--accent-wash); color: var(--accent-deep);
  font-family: var(--serif); font-size: 1.05rem; font-weight: 600;
}

/*
 * The handle, and only the handle, takes the drag: the rest of the card has to
 * stay scrollable and selectable. touch-action: none here means a finger that
 * lands on these dots is starting a drag rather than a scroll — which is why
 * the drag also waits out a short press before it takes over.
 */
.gstep__grip {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center; cursor: grab;
  border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-faint);
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.gstep__grip:hover { background: var(--paper-deep); color: var(--ink-soft); }
.gstep__grip:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
.gstep__grip:active { cursor: grabbing; }
.gstep__grip span {
  width: 12px; height: 19px;
  background-image: radial-gradient(currentColor 1.6px, transparent 1.8px);
  background-size: 6px 5px;
}

.gstep__text { min-height: 4.5rem; resize: none; overflow: hidden; }

/* Tops aligned, not centres: each photo now carries a caption and a button
   under it, and those can wrap to different heights. */
.gstep__shots { display: flex; flex-wrap: wrap; gap: .5rem; align-items: flex-start; margin-top: .6rem; }

/* The BOX grows with what is under the photograph; the photograph itself stays
   a fixed square.
   It used to be a fixed 108px square with overflow:hidden, which was right when
   a thumbnail was only ever a picture and a remove button. Adding a caption
   field and a notes button under it put both of them outside that square, where
   overflow:hidden clipped them away — present in the DOM, findable by a script,
   and invisible to the person using it. */
.gstep__shot {
  position: relative; width: 140px; flex: none;
  background: transparent;
}
.gstep__shot img {
  width: 140px; height: 108px; object-fit: cover; display: block;
  border-radius: var(--radius-sm); border: 1px solid var(--rule);
  background: var(--paper-deep);
}
.gstep__shot--busy {
  display: grid; place-items: center; height: 108px;
  border-radius: var(--radius-sm); border: 1px solid var(--rule);
  background: var(--paper-deep);
}
.gstep__shot--busy .spinner { display: block; width: 2rem; height: 2rem; border-width: 2px; margin: 0; }
.gstep__shot-x {
  position: absolute; top: .2rem; right: .2rem;
  width: 30px; height: 30px; display: grid; place-items: center;
  border: 0; border-radius: 999px; cursor: pointer;
  /* The pill is deliberately white in both themes — it sits on a photograph —
     so the mark on it has to be pinned too. Letting --danger flip underneath it
     put a pale red on white after dark, at about 2:1. */
  background: rgba(255,255,255,.94); color: #C1554D;
  -webkit-tap-highlight-color: transparent;
}
.gstep__addshots { display: flex; gap: .5rem; flex-wrap: wrap; }

.gsteps__add { border-style: dashed; }

/* ── The view ──────────────────────────────────────────────────────────── */

.gv__hero {
  width: 100%; max-height: 420px; object-fit: cover;
  border-radius: var(--radius); margin-bottom: 1.75rem; display: block;
}
.gv__title { font-size: clamp(2rem, 5vw, 3rem); margin: 0 0 .35rem; }
.gv__meta { color: var(--ink); font-weight: 600; margin: 0 0 .2rem; }
.gv__by { color: var(--ink-soft); margin: 0 0 1.25rem; }
.gv__actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 2.25rem; }

/*
 * Paper on cloth — the same rule the rest of the app follows and this screen
 * was missing.
 *
 * styles.css puts it plainly: reading surfaces are laid on the tablecloth as
 * opaque white, so no body text is ever set over a pattern. The recipe view
 * gets that from `#recipe-view.rv`; a guide had nothing, so its steps and its
 * "what you'll need" list were reading straight off the gingham — which is
 * exactly where the check is hardest to read across.
 *
 * Same values as `.sheet` and `.rv`, deliberately: a guide and a recipe are two
 * pages of one binder, and they should sit on the page the same way.
 */
.gv, .gedit {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 2rem 2.25rem 3rem;
}

/* Edge to edge on a phone, where a margin costs more than the frame is worth. */
@media (max-width: 640px) {
  .gv, .gedit { padding: 1.25rem 1.1rem 1.75rem; border-radius: 0; border-inline: 0; }
}

/* The step photos already carry their own tint; on white it reads as a frame
   rather than as a second, competing surface. */
.gv__block { margin-bottom: 2.25rem; }
.gv__block h2 { font-family: var(--serif); font-size: 1.5rem; margin: 0 0 .75rem; }
.gv__block h3 { font-family: var(--serif); font-size: 1.1rem; font-weight: 600; margin: 1rem 0 .35rem; }

.gv__supplies { margin: 0; padding-left: 1.2rem; columns: 2; column-gap: 2.5rem; }
.gv__supplies li { margin-bottom: .3rem; break-inside: avoid; }

.gv__recipes { display: flex; flex-wrap: wrap; gap: .75rem; }
.gv-rcard {
  display: flex; align-items: center; gap: .75rem; text-decoration: none; color: var(--ink);
  padding: .4rem .9rem .4rem .4rem; min-height: 56px;
  background: var(--card); border: 1px solid var(--rule); border-radius: 999px;
  box-shadow: var(--shadow); font-weight: 600;
}
.gv-rcard:hover { border-color: var(--accent); }
.gv-rcard img, .gv-rcard__blank {
  width: 44px; height: 44px; flex: none; border-radius: 999px;
  object-fit: cover; display: grid; place-items: center;
  background: var(--paper-deep); font-size: 1.1rem;
}

.gv-steps { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.75rem; }
.gv-step { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); gap: 1rem; align-items: start; }
.gv-step__n {
  display: grid; place-items: center;
  width: 2.5rem; height: 2.5rem; border-radius: 999px;
  background: var(--accent); color: #fff;
  font-family: var(--serif); font-size: 1.25rem; font-weight: 600;
}
.gv-step__text { margin: .25rem 0 0; white-space: pre-wrap; font-size: 1.05rem; }

.gv-step__shots { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .85rem; }
.gv-shot {
  padding: 0; border: 1px solid var(--rule); border-radius: var(--radius-sm);
  background: var(--paper-deep); cursor: zoom-in; overflow: hidden;
  width: min(260px, 100%); -webkit-tap-highlight-color: transparent;
}
.gv-shot img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; }
.gv-shot:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* Straw after dark, a deeper square of cloth in daylight — the two themes want
   opposite panels here. Only the dark one needs an edge drawn, where the straw
   sits too close to the page to separate itself. In daylight the border is
   still there but transparent, so the panel's own colour shows through it and
   the box measures the same either way. */
.gv__notes {
  background: var(--paper-deep);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem; margin-top: 2rem;
}
.gv__notes h2 { font-family: var(--serif); font-size: 1.3rem; margin: 0 0 .4rem; }
.gv__notes p { white-space: pre-wrap; margin: 0; }

/* ── Lightbox ──────────────────────────────────────────────────────────── */

/* Deliberately the same dark scrim in both themes: this is a photo viewer, and
   a photo wants darkness around it whatever the rest of the app is wearing. */
.gv-lightbox {
  position: fixed; inset: 0; z-index: 300;
  cursor: zoom-out;
  background: rgba(12, 20, 30, .93);
  /* One row for the photograph, one for its notes, and the photograph's row is
     minmax(0, 1fr) so it gives up space rather than shoving the notes off the
     bottom of the screen. */
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  justify-items: center;
  align-items: center;
  padding:
    max(1rem, env(safe-area-inset-top))
    max(1rem, env(safe-area-inset-right))
    max(1rem, env(safe-area-inset-bottom))
    max(1rem, env(safe-area-inset-left));
}
.gv-lightbox img {
  display: block;
  width: 100%; height: 100%;
  border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
}
.gv-lightbox__close {
  position: absolute;
  top: max(.75rem, env(safe-area-inset-top));
  right: max(.75rem, env(safe-area-inset-right));
  width: 44px; height: 44px;
  display: grid; place-items: center; cursor: pointer;
  border: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .16); color: #fff;
  -webkit-tap-highlight-color: transparent;
}
.gv-lightbox__close:hover { background: rgba(255, 255, 255, .28); }
.gv-lightbox__close .ico { width: 1.4rem; height: 1.4rem; }

/* ── Touch ─────────────────────────────────────────────────────────────── */

/*
 * Nothing here is revealed by hover. On the iPad this is really used on, a
 * hover-only control is a control that does not exist — so the step's buttons,
 * the photo's remove ×, and the recipe chips' × are all permanently visible,
 * and the desktop only ever gets a quieter version of the same thing.
 */
@media (hover: hover) and (min-width: 1181px) {
  .gstep__bar .btn--quiet { opacity: .7; transition: opacity .12s; }
  .gstep:hover .gstep__bar .btn--quiet,
  .gstep:focus-within .gstep__bar .btn--quiet { opacity: 1; }
}

/*
 * `any-pointer: coarse`, not `hover: none`.
 *
 * An iPad in a Magic Keyboard — or with any trackpad or mouse paired — reports
 * `hover: hover`, so every rule below used to switch itself off on the exact
 * device this app is built for, reverting to mouse-sized targets under a finger.
 * `any-pointer: coarse` stays true whenever a finger is one of the ways in,
 * which is the question these rules are actually asking.
 */
@media (any-pointer: coarse) {
  .gstep__shot { width: 150px; }
  .gstep__shot img { width: 150px; height: 116px; }
  .gstep__shot--busy { height: 116px; }
  .gstep__shot-x { width: 44px; height: 44px; }
  .grec-chip { min-height: 52px; }
  .grec-chip__x { width: 44px; height: 44px; }
  .gv-shot { cursor: default; }
  .gstep__grip { cursor: default; }
  /* Nothing in the sheet needs enlarging: the buttons get their 44px from .btn
     and .btn--small above, and a card is the target — which is most of why
     tapping cards beats picking a name out of a dropdown in the first place. */
  .grec-sheet .rcard { cursor: default; }
}

/* Both orientations of an iPad: the step bar has room for its buttons in
   landscape and wraps to two rows in portrait, which is why it's a wrapping
   flex row rather than a grid. */
@media (max-width: 700px) {
  .gv__supplies { columns: 1; }
  .gv-step { grid-template-columns: 2rem minmax(0, 1fr); gap: .75rem; }
  .gv-step__n { width: 2rem; height: 2rem; font-size: 1.05rem; }
  .gstep__bar .btn--small { flex: 1 1 auto; }
  .gedit__who { margin-left: 0; }
  .gv__actions .btn, .gedit__actions .btn { flex: 1 1 auto; }

  /* On a phone the sheet's heading and its search box each want the full width,
     and the count bar has already gone full-width to match (see styles.css). */
  .grec-sheet__head { gap: .75rem; padding-bottom: .85rem; }
  .grec-sheet__intro, .grec-sheet__search { flex: 1 1 100%; max-width: none; }
  .grec-sheet__body { padding-top: 1rem; }
}

/* A phone on its side has almost no height to spare, and the sentence under the
   heading is the first thing that can go: the cards explain themselves. */
@media (max-height: 480px) {
  .grec-sheet__intro .hint { display: none; }
  .grec-sheet__head { padding-top: max(.6rem, env(safe-area-inset-top)); padding-bottom: .6rem; }
}

@media (prefers-reduced-motion: reduce) {
  .gsteps.is-reordering .gstep { transition: none; }
  .gstep__bar .btn--quiet { transition: none; }
}

/*
 * The same colours again, as light-dark() pairs.
 *
 * The rules above now carry only the daytime value, which every browser
 * understands; this block adds the evening half where light-dark() is
 * supported. Without the guard these declarations were simply invalid on an
 * older Safari, and an invalid `color` inherits — which on a filled blue
 * button meant near-white text on light blue.
 */
@supports (color: light-dark(#000, #fff)) {
  .gv-step__n { color: light-dark(#fff, #1B1917); }
  /* Straw after dark, a deeper square of cloth in daylight — the two themes want
   opposite panels here. Only the dark one needs an edge drawn, where the straw
   sits too close to the page to separate itself. In daylight the border is
   still there but transparent, so the panel's own colour shows through it and
   the box measures the same either way. */
.gv__notes { background: light-dark(var(--paper-deep), var(--wicker-wash));border: 1px solid light-dark(transparent, var(--rule)); }
}

/* ==========================================================================
   How it prints — the guide's page-template card.

   Two radiogroups rather than one: how tight the type is set and what shape
   the page takes are separate decisions, and a single list of six would invite
   reading them as six variants of the same thing.

   Sized like .tpl in styles.css on purpose — this is the recipe editor's
   template picker asked about a how-to, and it should look like it.
   ========================================================================== */

.gedit__legend {
  display: block; font-weight: 600; font-size: .95rem; margin-bottom: .45rem;
}

.gpicks { display: grid; gap: .4rem; }

.gpick {
  text-align: left; font: inherit; cursor: pointer; padding: .6rem .75rem;
  border: 1px solid var(--rule); border-radius: var(--radius-sm);
  background: var(--paper); color: inherit;
  /* 44px minimum touch target, and the padding above already clears it. */
  min-height: 44px;
}
.gpick__name { display: block; font-size: .95rem; font-weight: 600; }
.gpick__blurb { display: block; font-size: .8rem; color: var(--ink-faint); line-height: 1.35; }
.gpick[aria-checked="true"] { border-color: var(--accent); background: var(--accent-wash); }
.gpick:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }

/*
 * What it will actually cost in paper, in a sentence. This is the thing the
 * recipe editor has always shown and a guide never did — she could not find out
 * a how-to ran onto a second sheet until the second sheet came out.
 */
.gplan {
  margin: .9rem 0 0; padding: .7rem .8rem;
  border-radius: var(--radius-sm);
  background: var(--paper-deep);
  font-size: .88rem; line-height: 1.45;
}
.gplan strong { font-weight: 700; }

/* Roomier than a phone can give, so the two lines of a choice don't wrap. */
@media (min-width: 40rem) {
  .gpicks { grid-template-columns: 1fr 1fr; }
}

/* ---- Step titles ---------------------------------------------------------
   Above the body, and deliberately the first thing in the card. Titling every
   step and then filling the bodies in is how this writing is supposed to go —
   the titles are the outline — so the field she meets first is the one that
   builds it.
   ------------------------------------------------------------------------- */
.gstep__title {
  width: 100%;
  font-weight: 600;
  font-size: 1rem;
  padding: .5rem .6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: inherit;
  margin-bottom: .4rem;
}

/* ---- Photo captions ------------------------------------------------------
   Under the thumbnail it belongs to, because a caption is about one
   photograph and a box floating elsewhere would not say which.
   ------------------------------------------------------------------------- */
.gstep__cap {
  width: 100%;
  font-size: .8rem;
  padding: .3rem .4rem;
  margin-top: .25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: inherit;
}

/* ---- Callouts ------------------------------------------------------------ */
.gcalls { display: grid; gap: .4rem; margin-top: .5rem; }
.gcall {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: .4rem;
  align-items: start;
}
.gcall__kind { font-size: .85rem; padding: .35rem .4rem; }
.gcall__text {
  font-size: .9rem;
  padding: .4rem .5rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: inherit;
  resize: vertical;
}
@media (max-width: 640px) {
  .gcall { grid-template-columns: 1fr; }
}

/* ---- The four blocks after the last step --------------------------------- */
.gnotes { display: grid; gap: .6rem; margin-top: .6rem; }
@media (min-width: 720px) { .gnotes { grid-template-columns: 1fr 1fr; } }

/* ---- Starting from a shape -----------------------------------------------
   Offered only on a guide that has not been started, and it names the steps
   rather than writing them: a skeleton that arrives with sentences in it is a
   thing to delete, one that arrives with names on the steps turns "write a
   guide" into "fill these in".
   ------------------------------------------------------------------------- */
.gskel__row { display: grid; gap: .5rem; }
@media (min-width: 700px) { .gskel__row { grid-template-columns: repeat(3, 1fr); } }

.gskel__pick {
  text-align: left;
  font: inherit;
  cursor: pointer;
  padding: .7rem .8rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: inherit;
}
.gskel__pick strong { display: block; font-size: .95rem; }
.gskel__pick span { display: block; font-size: .8rem; color: var(--ink-faint); line-height: 1.35; }
.gskel__pick:hover, .gskel__pick:focus-visible { border-color: var(--accent); }

/* The button that opens the pin placer, under each photo's caption. Kept to
   one line: it sits in a narrow column and a two-line button reads as two
   controls. */
.gstep__pins {
  margin-top: .25rem;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==========================================================================
   Reading a guide — the same furniture the printed sheet has.

   What is on screen and what comes out of the printer should be the same
   guide. Titles, captions, pinned notes and callouts all existed on paper
   before they existed here, which meant a note she had placed was invisible
   in the app and appeared only in the print preview.
   ========================================================================== */

.gv-step__title { font-size: 1.02rem; font-weight: 700; margin: 0 0 .3rem; }

.gv-figure { margin: 0; display: flex; flex-direction: column; }
.gv-cap { font-size: .82rem; color: var(--ink-faint); line-height: 1.35; margin-top: .3rem; }

/* The marker sits ON the photograph; the words go underneath, exactly as they
   do on paper. A note laid over a thumbnail is unreadable at this size and
   covers the thing it points at. */
.gv-shot { position: relative; }

.gv-pin {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .66);
  border: 2px solid #fff;
  color: #fff;
  font: 700 .7rem/19px system-ui, sans-serif;
  text-align: center;
  pointer-events: none;
}
.gv-pin--big { width: 30px; height: 30px; font-size: .85rem; line-height: 27px; }

.gv-pins {
  margin: .3rem 0 0;
  padding-left: 1.1rem;
  font-size: .82rem;
  line-height: 1.4;
  color: var(--ink-faint);
}

.gv-calls { list-style: none; padding: 0; margin: .5rem 0 0; display: grid; gap: .35rem; }
.gv-call {
  font-size: .9rem;
  line-height: 1.4;
  padding: .35rem 0 .35rem .6rem;
  border-left: 3px solid var(--rule);
}
.gv-call b {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-right: .3rem;
  color: var(--ink-faint);
}
.gv-call--caution { border-left-color: var(--danger); }
.gv-call--ahead { border-left-color: var(--accent); }

/* The lightbox is where the notes are actually read. */

/* The frame has to hug the photograph exactly, because the pins are placed as
   percentages of IT — any letterboxing inside it puts every pin off by the
   same slice, and a note ends up pointing just below the thing it names.

   Hugging it needs BOTH limits at once: as wide as the stage allows, or as
   wide as the stage's height allows, whichever is less. `max-height: 100%`
   cannot say the second one — a percentage height counts for nothing when the
   parent's own height is automatic, and the parent's height here is the
   picture, which is what we were trying to measure. `cqh` asks the stage
   instead, which has a real height. Same trick as the camera viewfinder. */
.gv-lightbox__stage {
  container-type: size;
  width: 100%; height: 100%;
  min-height: 0;
  display: grid; place-items: center;
}
.gv-lightbox__frame {
  position: relative;
  line-height: 0;
  /* --shot-ratio is the photograph's own proportions, set once it has loaded.
     The fallback is only what is used for the instant before that. */
  width: min(100%, calc(100cqh * var(--shot-ratio, 1.4)));
  aspect-ratio: var(--shot-ratio, 1.4);
}
.gv-lightbox__pins {
  margin: .8rem 0 0;
  padding-left: 1.3rem;
  max-width: 42rem;
  /* Its own row, so a long list scrolls instead of stealing the photo's. */
  max-height: 30vh;
  overflow-y: auto;
  color: #fff;
  font-size: .95rem;
  line-height: 1.5;
  text-align: left;
  cursor: auto;
}
