/* -------------------------------------------------------------------------
   /poster — poster and meme builder.
   Loads after styles.css and consumes its tokens. Same manga language as
   /earn: ink gutters, screentone, hard offset shadows. Everything renders to
   a canvas in the browser; nothing is uploaded anywhere.

   Mobile first. One thumbable column below 64rem: the stage pins itself to
   the top of the viewport with the canvas capped at 46vh, and the control
   stack scrolls beneath it. 64rem and up: canvas left, 22rem rail right.
   ---------------------------------------------------------------------- */

:root {
  /* Hex fallbacks first, oklch (authoritative) second. */
  --panel: #fefbf3;
  --ink-soft: #4e4640;
  --tone: #e9e4d3;

  --panel: oklch(0.985 0.006 88);
  --ink-soft: oklch(0.4 0.015 55);
  --tone: oklch(0.93 0.01 80);
}

.pz {
  padding: 1.25rem 1rem 3rem;
}

@media (min-width: 48rem) {
  .pz {
    padding: 2.5rem 1.5rem 4rem;
  }
}

.pz__inner {
  max-width: 82rem;
  margin: 0 auto;
}

.pz__title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 5.5vw, 3rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.pz__title span {
  color: var(--primary);
}

.pz__sub {
  margin-top: 0.6rem;
  max-width: 52ch;
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.95rem;
}

/* ---- workbench --------------------------------------------------------
   Flex column below 64rem so the sticky stage has the whole grid box to
   travel in (a single-column CSS grid row would be exactly as tall as the
   stage itself and the pin would go nowhere). Grid from 64rem. */

.pz__grid {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 1.25rem;
  min-width: 0;
}

@media (min-width: 64rem) {
  .pz__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 22rem;
    gap: 1.5rem;
    align-items: start;
  }
}

/* ---- stage ---- */

.stage {
  position: sticky;
  top: 0;
  padding: 0.75rem;
  border: 3px solid var(--foreground);
  background: var(--panel);
  box-shadow: 5px 5px 0 var(--foreground);
}

@media (min-width: 64rem) {
  .stage {
    top: 1rem;
    padding: 1rem;
    border-width: 4px;
    box-shadow: 8px 8px 0 var(--foreground);
  }
}

.stage__frame {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 9rem;
  background-image:
    linear-gradient(45deg, var(--tone) 25%, transparent 25%),
    linear-gradient(-45deg, var(--tone) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--tone) 75%),
    linear-gradient(-45deg, transparent 75%, var(--tone) 75%);
  background-size: 18px 18px;
  background-position: 0 0, 0 9px, 9px -9px, -9px 0;
}

@media (min-width: 48rem) {
  .stage__frame {
    min-height: 18rem;
  }
}

#canvas {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  /* Thumb-dragged, so the browser must never claim the gesture to scroll. */
  touch-action: none;
  /* Capped so the controls are never pushed off a phone screen. */
  max-height: 46vh;
  box-shadow: 5px 5px 0 var(--foreground);
}

@media (min-width: 64rem) {
  #canvas {
    max-height: 70vh;
    box-shadow: 8px 8px 0 var(--foreground);
  }
}

.stage__meta {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
  color: var(--ink-soft);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

@media (min-width: 48rem) {
  .stage__meta {
    font-size: 0.72rem;
  }
}

/* Small caption under the frame. */
.stage__hint {
  margin-top: 0.5rem;
  color: var(--ink-soft);
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
}

/* ---- control stack ---- */

.ctrl {
  border: 3px solid var(--foreground);
  background: var(--panel);
  box-shadow: 5px 5px 0 var(--foreground);
}

@media (min-width: 64rem) {
  .ctrl {
    box-shadow: 6px 6px 0 var(--foreground);
  }
}

.ctrl + .ctrl {
  margin-top: 1rem;
}

.ctrl__head {
  padding: 0.6rem 0.75rem;
  background: var(--foreground);
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.ctrl__body {
  padding: 0.75rem;
}

@media (min-width: 48rem) {
  .ctrl__body {
    padding: 0.9rem;
  }
}

.f {
  margin-bottom: 0.9rem;
  min-width: 0;
}

.f:last-child {
  margin-bottom: 0;
}

/* :last-child still matches a hidden .f, so removing the scan code left a 14px
   ragged tail under the last control that was still on screen. Zero the margin
   on the last VISIBLE one instead: no following sibling that is not hidden. */
.f:not(:has(~ .f:not([hidden]))) {
  margin-bottom: 0;
}

.f > label,
.f__legend {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.f input[type="text"],
.f input[type="url"],
.f select {
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.6rem;
  border: 3px solid var(--foreground);
  border-radius: 0;
  background: var(--panel);
  color: var(--foreground);
  font-family: var(--font-sans);
  /* 1rem keeps iOS from zooming the page on focus. */
  font-size: 1rem;
  font-weight: 600;
}

.f input[type="range"] {
  width: 100%;
  min-height: 44px;
  accent-color: var(--primary);
}

/* segmented choices — buttons wrap, never overflow their panel */

.seg {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  max-width: 100%;
}

.seg button {
  flex: 1 1 auto;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.45rem 0.6rem;
  border: 3px solid var(--foreground);
  background: var(--panel);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.2;
  cursor: pointer;
  transition:
    background-color 140ms ease,
    color 140ms ease,
    box-shadow 140ms ease,
    transform 140ms ease;
}

.seg button:hover {
  background: var(--gold);
}

.seg button[aria-pressed="true"] {
  background: var(--foreground);
  color: var(--gold);
}

/* image library — 3 up on a phone, 4 up from sm */

.lib {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.4rem;
}

@media (min-width: 40rem) {
  .lib {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.lib button {
  position: relative;
  min-height: 44px;
  padding: 0;
  border: 3px solid var(--foreground);
  background: var(--panel);
  aspect-ratio: 1;
  overflow: hidden;
  cursor: pointer;
  transition:
    background-color 140ms ease,
    color 140ms ease;
}

.lib img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lib button[aria-pressed="true"] {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
}

/* Applied by the script to whatever the thumb last picked. */
.is-picked {
  outline: 3px dashed var(--primary);
  outline-offset: 2px;
}

.lib__own {
  display: grid;
  place-items: center;
  padding: 0.35rem;
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.35;
}

/* export row */

.out {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.out button {
  flex: 1 1 auto;
  min-height: 44px;
  padding: 0.65rem 0.6rem;
  border: 3px solid var(--foreground);
  box-shadow: 4px 4px 0 var(--foreground);
  font-family: var(--font-display);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color 140ms ease,
    box-shadow 140ms ease,
    transform 140ms ease;
}

.out button:hover {
  background: var(--gold);
}

.out button:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--foreground);
}

.note {
  margin-top: 0.6rem;
  color: var(--ink-soft);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.5;
}

.hint {
  padding: 0.5rem 0.6rem;
  border: 2px dashed var(--ink-soft);
  color: var(--ink-soft);
  font-size: 0.72rem;
  font-weight: 600;
}

/* ---- motion ---- */

@media (prefers-reduced-motion: reduce) {
  .seg button,
  .out button,
  .lib button {
    transition: none;
  }

  .out button:active {
    transform: none;
    box-shadow: 4px 4px 0 var(--foreground);
  }
}

/* -------------------------------------------------------------------------
   Fixes after first look
   ---------------------------------------------------------------------- */

/* .page sets overflow-x: hidden, which makes it a scroll container, so every
   position: sticky inside it pins to .page instead of the viewport and never
   engages. clip does the same visual job without creating one. Scoped to this
   page so the homepage hero is untouched. */
.page--poster {
  overflow-x: clip;
}

/* Even, wrapping cells. flex:1 1 auto sized each button to its label, so "X"
   came out a third the width of "Earn page". */
.seg {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.25rem, 1fr));
}

.seg button {
  flex: none;
  width: 100%;
}

/* One primary action, not four competing ones. */
.out button {
  background: var(--panel);
  color: var(--foreground);
}

.out button:first-child {
  background: var(--primary);
  color: var(--primary-foreground);
}

.out button:hover {
  background: var(--gold);
}

@media (min-width: 64rem) {
  /* A wider rail and a capped canvas column stop the artwork stranding in the
     middle of a very wide empty track. */
  .pz__grid {
    grid-template-columns: minmax(0, 1fr) 25rem;
  }

  .stage {
    align-self: start;
  }

  #canvas {
    max-height: 76vh;
  }
}


/* The checker was louder than the artwork it sits behind. Keep the idea, drop
   the contrast, and let the poster be the brightest thing on the page. */
.stage__frame {
  background-color: #f2efe6;
  background-image:
    linear-gradient(45deg, rgba(10, 10, 10, 0.045) 25%, transparent 25%),
    linear-gradient(-45deg, rgba(10, 10, 10, 0.045) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, rgba(10, 10, 10, 0.045) 75%),
    linear-gradient(-45deg, transparent 75%, rgba(10, 10, 10, 0.045) 75%);
  background-size: 22px 22px;
  background-position: 0 0, 0 11px, 11px -11px, -11px 0;
  padding: 0.75rem;
}

@media (min-width: 64rem) {
  .stage__frame {
    padding: 1rem;
  }
}

/* ---- move vs scroll ---------------------------------------------------- */

/* The stage is sticky and the control panels come after it in the document,
   so without a stacking context they paint straight over the preview. */
.stage {
  z-index: 5;
}

/* Scrolling wins by default. The Move button opts into dragging, which is the
   only way to have both on a touch screen. */
#canvas {
  touch-action: pan-y;
}

.movebtn {
  min-height: 44px;
  padding: 0.5rem 0.7rem;
  border: 3px solid var(--foreground);
  background: var(--panel);
  color: var(--foreground);
  font-family: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}

/* A landscape phone is only ~390px tall. A sticky stage plus its captions eats
   the whole screen and the controls become unreachable, so let it scroll. */
@media (max-height: 34rem) {
  .stage {
    position: static;
  }

  .stage__frame {
    min-height: 0;
  }

  #canvas {
    max-height: 58vh;
  }
}

/* ---- pre-made poster gallery ------------------------------------------ */

.gal {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 4px solid var(--foreground);
}

.gal__head {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 4vw, 2rem);
  letter-spacing: -0.01em;
}

.gal__sub {
  margin: 0.5rem 0 1.25rem;
  max-width: 52ch;
  color: var(--ink-soft, #4e4640);
  font-weight: 600;
  font-size: 0.9rem;
}

/* ---- gallery tiles ----------------------------------------------------
   The artwork is the hero, so the tile is a frame around it rather than a
   picture with two buttons bolted on. The poster image itself is the primary
   action; Edit is reinforcement, Save is the quiet second option.

   Hover and focus lift is decorative and therefore lives behind
   (hover: hover) and (pointer: fine). The buttons, the border and the shadow
   all exist in the resting state, so a finger or a keyboard sees the same
   tile. Grid columns are minmax(0, 1fr) and the shadow never reaches past
   the .pre gutter, so nothing overflows horizontally.
   ---------------------------------------------------------------------- */

.pre {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
}

@media (min-width: 40rem) {
  .pre {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 64rem) {
  .pre {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.pre__item {
  display: flex;
  flex-direction: column;
  margin: 0;
  border: 2px solid var(--foreground);
  background: var(--panel);
  box-shadow: 4px 4px 0 var(--foreground);
  transition:
    box-shadow 150ms ease,
    transform 150ms ease;
}

@media (min-width: 48rem) {
  .pre__item {
    border-width: 3px;
    box-shadow: 5px 5px 0 var(--foreground);
  }
}

.pre__pick {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.pre__pick img {
  display: block;
  width: 100%;
  height: auto;
}

.pre__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* Ink floor under the artwork, so the chrome reads as one bar of the card
     rather than two buttons stuck under a picture. */
  border-top: 2px solid var(--foreground);
  margin-top: auto;
}

@media (min-width: 48rem) {
  .pre__row {
    border-top-width: 3px;
  }
}

.pre__row button {
  min-height: 44px;
  padding: 0.6rem 0.35rem;
  border: 0;
  background: var(--panel);
  color: var(--foreground);
  font-family: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.2;
  cursor: pointer;
  transition:
    background-color 150ms ease,
    color 150ms ease;
}

/* Edit is reinforcement for a click the whole image already makes: same ink
   label as the panel furniture, cell slightly shaded to read first. */
.pre__row button:first-child {
  background: var(--tone);
}

/* Save is the secondary option: quietest label, behind the cell divider. */
.pre__row button:last-child {
  border-left: 2px solid var(--foreground);
  color: var(--ink-soft);
}

@media (min-width: 48rem) {
  .pre__row button:last-child {
    border-left-width: 3px;
  }
}

.pre__row button:hover {
  background: var(--secondary);
  color: var(--foreground);
}

.pre__row button:active {
  background: var(--gold);
  color: var(--foreground);
}

/* Focus is a real outline, not a colour change, and it is drawn outside the
   tile so it is never eaten by the row's border. */
.pre__pick:focus-visible,
.pre__row button:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 3px;
}

.pre__pick:focus-visible {
  position: relative;
  z-index: 1;
}

/* Pointer-only affordances. On touch the resting state above is the whole
   design, so nothing is hidden from a finger. */
@media (hover: hover) and (pointer: fine) {
  .pre__item:hover {
    transform: translate(-2px, -2px);
    box-shadow: 7px 7px 0 var(--foreground);
  }
}

@media (prefers-reduced-motion: reduce) {
  .pre__item,
  .pre__row button {
    transition: none;
  }

  .pre__item:hover {
    transform: none;
  }

  .pre__row button:active {
    transform: none;
  }
}

/* ---- stage toolbar on small screens -------------------------------------
   The hint ran to two lines and left Move and Save cramped and stranded
   beneath it. Give the buttons their own full-width row and equal weight.
   ---------------------------------------------------------------------- */

.stage__hint {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
  align-items: center;
}

.stage__tools {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  width: 100%;
}

.stage__tools .movebtn,
.stage__tools .menu {
  width: 100%;
}

.stage__tools .menu .movebtn {
  width: 100%;
}

@media (min-width: 48rem) {
  .stage__hint {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .stage__tools {
    width: auto;
    grid-template-columns: auto auto;
  }
}

/* ---- save menu ---------------------------------------------------------
   Lost when the carousel block was replaced, which left the menu items as
   four bare links flowing inline under the toolbar.
   ---------------------------------------------------------------------- */

.menu {
  position: relative;
  display: inline-block;
}

.menu__pop {
  /* Hangs off the button's own edge instead of floating 0.35rem clear of it,
     so it reads as attached chrome rather than an independent card. */
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 14;
  display: grid;
  min-width: 12.5rem;
  border: 3px solid var(--foreground);
  border-top: 0;
  background: var(--panel);
  box-shadow: 6px 6px 0 var(--foreground);
}

.menu__pop button {
  min-height: 46px;
  padding: 0 1rem;
  border: 0;
  border-bottom: 2px solid var(--foreground);
  background: var(--panel);
  color: var(--foreground);
  font-family: var(--font-display);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}

.menu__pop button:last-child {
  border-bottom: 0;
}

.menu__pop button:hover {
  background: var(--gold);
}

.menu__pop button:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: -3px;
}

/* ---- tap-to-edit panel -------------------------------------------------
   Sits in the flow under the canvas. Absolutely positioning it meant it
   covered the poster at one anchor and the toolbar at the other.
   ---------------------------------------------------------------------- */

.ied {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.35rem 0.5rem;
  align-items: center;
  margin-top: 0.6rem;
  padding: 0.6rem;
  border: 3px solid var(--foreground);
  background: var(--panel);
}

.ied label {
  grid-column: 1;
  font-family: var(--font-display);
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft, #4e4640);
}

.ied input {
  grid-column: 1;
  width: 100%;
  min-height: 44px;
  padding: 0.35rem 0.55rem;
  border: 2px solid var(--foreground);
  border-radius: 0;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
}

.ied button {
  grid-column: 2;
  grid-row: 1 / span 4;
  align-self: stretch;
  min-height: 44px;
  padding: 0 1rem;
  border: 3px solid var(--foreground);
  background: var(--primary);
  color: var(--primary-foreground);
  font-family: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.ied button:hover {
  background: var(--gold);
}


/* The trigger looked identical open and closed, so nothing tied the panel back
   to it. State uses ink and gold; orange stays reserved for primary actions. */
.movebtn[aria-expanded="true"] {
  background: var(--foreground);
  color: var(--gold);
}

.movebtn[aria-pressed="true"] {
  background: var(--foreground);
  color: var(--gold);
}
