/* photos2gif - Never or Forever's FF1 menus: blue windows with the sheet's border at 2x,
   the 8x8 font and the hand pointing at the chosen command at 1.75x. One sheet pixel of the
   window = --px, of the font and hand = --fpx. */
@font-face {
  font-family: 'NoF Menu';
  src: url(/ui/nof-font.woff2?v=3) format('woff2');
  font-display: block;
}
:root {
  --px: 2px;
  --fpx: 1.75px;          /* the main text: 14 px (designer, 2026-10-15: "smaller font in general in terms of the bigger font size", then "let's increase the main font a bit") */
  --small: 8px;           /* the small text: the font at 1x (status line, frame numbers, footer) */
  --blue: rgb(36, 24, 142);
  --white: #fcfcfc;
  --grey: rgb(117, 117, 117);
  --light: rgb(188, 188, 188);
  --gold: #f8d878;
  --font: 'NoF Menu', 'Courier New', monospace;
  color-scheme: dark;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; height: 100%; overflow: hidden; background: #000; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  color: var(--white);
  font: calc(8 * var(--fpx)) / calc(12 * var(--fpx)) var(--font);
  -webkit-font-smoothing: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  overscroll-behavior: none;
}
button, input, select { font: inherit; color: inherit; }
img, canvas { image-rendering: auto; }

/* ---- the window ---- */
.win {
  position: relative;
  background: var(--blue);
  background-clip: padding-box;   /* scaled by odd amounts, blue under the border showed past its edge */
  border: calc(8 * var(--px)) solid transparent;
  border-image: url(/ui/window.png?v=4) 8 fill / calc(8 * var(--px)) repeat;
  image-rendering: pixelated;
  padding: calc(2 * var(--px)) calc(3 * var(--px));
}

/* ---- one fixed layout, scaled to fit (designer, 2026-10-15: "have it be what we will see no
   matter what the resolution of a phone", "it scale so it's always the same layout").
   #app is 400 x 560; app.js fit() scales it as a whole into #fit and centres it. Every size
   below is in that 400 x 560 frame. Sideways phones and iPads get the wide layout (the end of
   this file). The fallbacks come first for browsers
   without env(). */
#fit {
  position: fixed; overflow: hidden;
  top: 0; right: 0; bottom: 0; left: 0;
  top: env(safe-area-inset-top, 0px); right: env(safe-area-inset-right, 0px);
  bottom: env(safe-area-inset-bottom, 0px); left: env(safe-area-inset-left, 0px);
  bottom: 26px; bottom: calc(env(safe-area-inset-bottom, 0px) + 26px);   /* the links under it */
}
body.with-ad #fit { bottom: 176px; bottom: calc(env(safe-area-inset-bottom, 0px) + 176px); }   /* and the banner's window */
/* 560 tall since 2026-10-15 (was 720), so a banner and the links fit under it without the app
   shrinking much (designer: "compress every screen so a banner can stay at the bootm", picked
   B from mockups). */
#app {
  position: absolute; top: 0; left: 0; width: 400px; height: 560px; overflow: hidden;
  transform-origin: 0 0; visibility: hidden;   /* shown once fit() has scaled it */
  display: flex; flex-direction: column; padding: 0 4px; background: #000;
}

/* ---- the GIF preview, always on top (designer, 2026-10-15: "we should always have the gif
   preview present, and below that settings and such change") ---- */
/* The title: its own window at the top of every screen, the camera too. Top left is Make GIF
   on the main screen and Back everywhere else, always in the same spot (designer, 2026-10-15:
   "a universal back button at the top would be good instead of "done"", "top left", "no make
   gif upper left, phots2gif can stay upper right"). The name on the right never moves. */
#title { height: 60px; flex: none; display: grid; grid-template-columns: 1fr auto; align-items: center; padding-top: 0; padding-bottom: 0; }
#title h1 { grid-column: 2; font: inherit; margin: 0; white-space: nowrap; }
#title-btn { grid-column: 1; justify-self: start; width: auto; min-height: 28px; padding-top: 0; padding-bottom: 0; }
#stage { height: 278px; flex: none; display: flex; flex-direction: column; padding-bottom: 0; }
#view-wrap { position: relative; flex: 1; min-height: 0; }
#gif { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; }
#gif.pix { image-rendering: pixelated; }
#gif:not([src]) { visibility: hidden; }   /* a GIF smaller than its box keeps hard pixels */
#view-empty { position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: flex; align-items: center; justify-content: center; text-align: center; color: var(--light); padding: 0 12px; }
/* The status line: frame, size, speed and file size, small, every field a fixed width so
   nothing moves when a number changes (designer, 2026-10-15: "a uniform way of showing
   frame, fps etc. and it should be smaller"). */
/* Centred between the GIF and the frame: 8 px above the letters, 8 below (with the window's
   own blue under it). Text everywhere sits in the middle of its row (designer, 2026-10-15:
   "make sure verything across the app is vertically centered when it comes to text"). */
#status {
  flex: none; height: 17px; padding-top: 6px; display: grid; grid-template-columns: 8em 10em 9em 1fr;   /* "0.25 fps" */
  font-size: var(--small); line-height: 11px; color: var(--light); white-space: nowrap;
}
#st-kb { text-align: right; }

/* ---- what is under the preview: one panel at a time ---- */
#panel { height: 222px; flex: none; position: relative; }
.panel { height: 100%; display: flex; flex-direction: column; }
/* Settings and Crop get a shorter preview and more room under it (designer, 2026-10-15:
   "Settings shorter"). */
#app[data-mode=settings] #stage, #app[data-mode=crop] #stage { height: 220px; }
#app[data-mode=settings] #panel, #app[data-mode=crop] #panel { height: 280px; }
footer { position: fixed; left: 0; right: 0; bottom: 0; bottom: env(safe-area-inset-bottom, 0px); height: 26px; box-sizing: border-box;
  color: var(--grey); text-align: center; font-size: var(--small); line-height: 10px; padding-top: 3px; }
footer a { color: var(--light); }

/* ---- the timeline ---- */
#tl-win { height: 114px; flex: none; }
#tl-wrap { position: relative; }
#timeline {
  display: flex; height: 74px; overflow-x: auto; overflow-y: hidden;
  padding: 5px 2px; scroll-behavior: smooth; touch-action: pan-x;
  scrollbar-width: none;   /* a phone shows none either; the PC must look the same */
}
#timeline::-webkit-scrollbar { display: none; }
.thumb {
  position: relative; flex: 0 0 auto; height: 64px; border: 2px solid transparent;
  background: #000; cursor: pointer; padding: 0;
}
.thumb canvas { display: block; height: 100%; }
.thumb .n { position: absolute; left: 1px; bottom: 0; font-size: var(--small); line-height: 8px; background: rgba(36, 24, 142, .85); padding: 1px 2px; }
.thumb + .thumb { margin-left: 6px; }
.thumb.on { border-color: var(--white); outline: 2px solid #000; }
.thumb.lift { opacity: .35; }
#drag-ghost { position: absolute; z-index: 50; pointer-events: none; border: 2px solid var(--gold); opacity: .9; height: 64px; }
#drop-mark { position: absolute; top: 5px; bottom: 5px; width: 4px; background: var(--gold); pointer-events: none; display: none; }
#tl-empty { color: var(--light); padding: 0 4px; display: flex; align-items: center; }

/* ---- command menus: the hand points at the chosen one ---- */
.cmds { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 0 4px; gap: 0 4px; align-content: start; }
/* The main commands: Frame across, then Add and GIF side by side. Each window's heading is a
   small box of its own in the same pixel frame (at 1x, with the 1x text), on the window's top
   edge at the upper left, sticking out into a gap above it (designer, 2026-10-15: "design a
   smaller break out box in the upper left of each frame to house the title using the pixelart
   frame style instead of having it in teh frame itself"). */
#menu { flex: 1; display: flex; flex-direction: column; }
.sect { margin-top: 12px; }
#m-frame, .pair > .win { height: 96px; }
/* Frame shows only once a frame is tapped, in place of Add and GIF (designer, 2026-10-15: "maybe
   even Frame options be something that pops up only when you need them"). */
#m-frame { display: none; }
#app.frame-open #m-frame { display: block; }
#app.frame-open .pair { display: none; }
.pair { display: flex; }
.pair > .win { flex: 1 1 auto; min-width: 0; }   /* each as wide as its words need */
.sect h2 {
  position: absolute; top: -26px; left: -8px; z-index: 1;   /* from the window's inside edge: 10 px above it, 8 px in from its left */
  margin: 0; padding: 0 4px; font: inherit; font-size: var(--small); line-height: 11px; color: var(--white); white-space: nowrap;   /* 11: whole pixels above and below */
  background: var(--blue); background-clip: padding-box;
  border: 8px solid transparent; border-image: url(/ui/window.png?v=4) 8 fill / 8px repeat; image-rendering: pixelated;
}
/* Columns as wide as their words, spread across: at 14 px three equal columns are too narrow
   for "← Move" and "Delete", two for "Use on all". */
.cmds.three { grid-template-columns: repeat(3, max-content); justify-content: space-between; }
#p-crop .cmds { grid-template-columns: repeat(2, max-content); justify-content: space-between; }
.cmd {
  position: relative; display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 3.5px 0 3.5px calc(20 * var(--fpx)); cursor: pointer; min-height: 28px;   /* rows sized to the 14 px text */
  white-space: nowrap;
}
.cmd:disabled { color: var(--grey); cursor: default; }
.cmd.on::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: calc(17 * var(--fpx)); height: calc(13 * var(--fpx));
  background: url(/ui/hand.png?v=3) 0 0 / 100% 100% no-repeat; image-rendering: pixelated;
}
.cmd:focus-visible::before {   /* its own rule: Safari before iOS 15.4 drops a rule naming :focus-visible */
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: calc(17 * var(--fpx)); height: calc(13 * var(--fpx));
  background: url(/ui/hand.png?v=3) 0 0 / 100% 100% no-repeat; image-rendering: pixelated;
}
.cmd:focus { outline: none; }
.cmds.one { grid-template-columns: 1fr; }

/* ---- settings: label and value in rows; the picked one changes with the arrow bar (FF config menu style) ---- */
#set-win { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#set-swatches { display: block; flex: none; width: 100%; height: 8px; margin-bottom: 4px; image-rendering: pixelated; }
#set-scroll { position: relative; flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
#set-scroll::-webkit-scrollbar { display: none; }
/* Each row is one tap target: tapping it puts the hand on it, and the big arrow bar under the
   list changes it (designer, 2026-10-15: "on my iphone it feels a little challenging to click on
   the arrows", "tap a row big arrow bar is good"). */
.row { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; height: 28px; padding-left: calc(20 * var(--fpx)); cursor: pointer; }
.row .label { color: var(--white); white-space: nowrap; }
.row .val { color: var(--gold); white-space: nowrap; }
.row.pick::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: calc(17 * var(--fpx)); height: calc(13 * var(--fpx));
  background: url(/ui/hand.png?v=3) 0 0 / 100% 100% no-repeat; image-rendering: pixelated;
}
/* The bar under the list: one slider for whichever row is picked (designer, 2026-10-15: "i think
   slider for everything is better"); press anywhere on the bar and drag. */
#adj { flex: none; height: 72px;   /* designer, 2026-10-15: "this can be shorter vertically" (was 88) */
  display: flex; flex-direction: column; justify-content: center; touch-action: none; cursor: pointer; }
/* Never or Forever's menu slider (its src/ui.js drawSlider) at 2x: a white rail with a grey row
   under it, a white notch for each stop, a white knob edged in grey. */
#adj-slider { position: relative; height: 32px; margin: 0 16px; }
#adj-slider .rail { position: absolute; left: 0; right: 0; top: 15px; height: 2px; background: #fff; box-shadow: 0 2px 0 var(--grey); }
#adj-slider .ticks i { position: absolute; top: 13px; width: 2px; height: 6px; margin-left: -1px; background: #fff; }
#adj-slider .knob { position: absolute; top: 5px; width: 14px; height: 22px; margin-left: -7px; background: #fff; border: 2px solid var(--grey); }
#set-scroll .cmds { margin-top: 6px; }

/* ---- crop ---- */
#crop-body { position: relative; flex: 1; min-height: 0; overflow: hidden; touch-action: none; display: flex; align-items: center; justify-content: center; }
#crop-canvas { touch-action: none; }
#crop-box { position: absolute; border: 2px solid var(--white); box-shadow: 0 0 0 9999px rgba(0, 0, 0, .55); touch-action: none; cursor: move; }
#crop-box::after { content: ''; position: absolute; top: 33.3%; bottom: 33.3%; left: 0; right: 0; border-top: 1px solid rgba(255,255,255,.35); border-bottom: 1px solid rgba(255,255,255,.35); pointer-events: none; }
#crop-box::before { content: ''; position: absolute; top: 0; bottom: 0; left: 33.3%; right: 33.3%; border-left: 1px solid rgba(255,255,255,.35); border-right: 1px solid rgba(255,255,255,.35); pointer-events: none; }
.handle { position: absolute; width: 24px; height: 24px; background: var(--white); border: 3px solid #000; touch-action: none; }
.handle.nw { left: -12px; top: -12px; cursor: nwse-resize; }
.handle.ne { right: -12px; top: -12px; cursor: nesw-resize; }
.handle.sw { left: -12px; bottom: -12px; cursor: nesw-resize; }
.handle.se { right: -12px; bottom: -12px; cursor: nwse-resize; }

/* ---- camera: everything under the title (designer, 2026-10-15: "camera", to keeping it full; the title is on every screen) ---- */
#camera { position: absolute; top: 60px; right: 0; bottom: 0; left: 0; z-index: 20;   /* under the title */ background: #000; display: flex; flex-direction: column; }
#camera .body { flex: 1; min-height: 0; position: relative; overflow: hidden; touch-action: none; }
#cam-frame { position: absolute; overflow: hidden; }
#cam-video { display: block; width: 100%; height: 100%; transform-origin: 50% 50%; }
#cam-onion { position: absolute; opacity: .4; pointer-events: none; }
#cam-zoom {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  background: var(--blue); border: 2px solid var(--white); color: var(--white); padding: 4px 0; cursor: pointer;
  width: calc(5 * 8 * var(--fpx) + 20px); text-align: center; white-space: nowrap;
}
/* Fixed widths, so a longer number never moves anything ("999 taken", "10.0x"). The count
   sits in the bar where Done was. */
#cam-count { margin-left: 16px; color: var(--light); width: calc(9 * 8 * var(--fpx)); white-space: nowrap; }
#cam-focus { position: absolute; width: 64px; height: 64px; margin: -32px 0 0 -32px; border: 2px solid var(--gold); pointer-events: none; }
#cam-focus.go { animation: focus-in .3s ease-out; }
@keyframes focus-in { from { transform: scale(1.5); opacity: .4; } to { transform: scale(1); opacity: 1; } }
#cam-flash { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #fff; opacity: 0; pointer-events: none; transition: opacity .25s; }
#cam-mask { position: absolute; border: 2px dashed rgba(252, 252, 252, .7); pointer-events: none; box-shadow: 0 0 0 9999px rgba(0, 0, 0, .45); }
/* Commands on the left with room for their words, the shutter off to the right (designer,
   2026-10-15: "put it off to the right so we can have more text to the left"). */
.cam-bar { flex: none; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
.cam-bar .cmds { display: flex; align-items: center; }
.cam-bar .cmd { width: auto; padding-left: 0; }   /* Ghost has its box instead of the hand */
/* The shutter: the original round button, smaller (designer, 2026-10-15: "the shutter is still too big"). */
#snap {
  width: 46px; height: 46px; margin: 0 6px 0 4px; border-radius: 50%; border: 5px solid var(--white);
  background: var(--blue); cursor: pointer; box-shadow: 0 0 0 3px #000, 0 0 0 5px var(--light);
}
#snap:active { background: var(--white); }

/* ---- messages ---- */
#msg { position: absolute; left: 10px; right: 10px; bottom: 30px; z-index: 60; display: flex; align-items: center; justify-content: space-between; }
#msg-undo { margin-left: 8px; }
#busy { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 70; background: rgba(0, 0, 0, .6); display: flex; align-items: center; justify-content: center; }
#busy .win { width: calc(20 * 8 * var(--px)); text-align: center; }   /* fixed: the text changes, the box does not */
.bar-meter { height: 8px; background: #000; margin-top: 6px; }
.bar-meter i { display: block; height: 100%; width: 0; background: var(--white); }

/* ---- ad: one 320 x 100 banner under the layout, outside it (an ad is never scaled), in a window
   like the app's, its label in a box on the bottom edge at the right (designer, 2026-10-15:
   "banner ad in a FF frame", then the label moved there and "not plural"). AdSense's help page
   allows only "Advertisements" or "Sponsored Links" above an ad and says nothing about a label
   under it or the singular. Hidden until an ad unit is set up. ---- */
#ad { position: fixed; left: 0; right: 0; bottom: 26px; bottom: calc(env(safe-area-inset-bottom, 0px) + 26px); height: 150px;
  display: flex; justify-content: center; align-items: flex-end; }
#ad-win { box-sizing: content-box; width: 320px; height: 100px; margin: 0 0 12px; padding: 0; }
/* The heading box turned upside down: on the bottom edge, 8 px in from the right, 10 px out below. */
#ad-win h2 { top: auto; left: auto; bottom: -26px; right: -8px; }
/* Screens under 352 wide (the first iPhone SE is 320) have room for the banner but not its frame:
   the frame goes, the label stays at its bottom right. */
@media (max-width: 351px) {
  #ad-win { border: 0; border-image: none; background: none; }
  #ad-win h2 { bottom: -12px; right: 0; }
}
#ad-slot { width: 320px; height: 100px; overflow: hidden; line-height: 0; }
/* The house ad: one 320 x 100 picture, drawn at 3x. */
#ad .house { display: block; width: 320px; height: 100px; }
#ad .house img { display: block; width: 320px; height: 100px; }

/* ---- the wide layout, for phones held sideways and iPads (app.js fit() picks it and sets its
   height and the panel's): the photo on the left under the title, the panel on the right, the
   banner in its frame under the panel and the links under the photo, both placed by fit()
   (designer, 2026-10-15: "new is fine but i want the ad framed"). The panel's column is the
   wider one so the banner's frame fits under it. ---- */
body.wide #fit { bottom: 26px; bottom: calc(env(safe-area-inset-bottom, 0px) + 26px); }
body.wide #app { width: 800px; display: grid; grid-template-columns: 336px 456px; grid-template-rows: 60px minmax(0, 1fr); }
body.wide #title { grid-column: 1; grid-row: 1; padding-left: 0; padding-right: 0; }   /* Make GIF and photos2gif need 287 of its 292 */
body.wide #app #stage { grid-column: 1; grid-row: 2; height: auto; }
body.wide #app #panel { grid-column: 2; grid-row: 1 / span 2; align-self: start; height: var(--panel-h); }
body.wide #app[data-mode=crop] #view-wrap { display: none; }   /* Crop's picture takes its place */
/* The camera: the picture where the photo is, its commands and the shutter over the panel. */
body.wide #camera { left: 4px; right: auto; width: 336px; }
body.wide .cam-bar { position: absolute; left: 100%; top: -60px; width: 456px; height: var(--panel-h);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 28px; }
/* Black under its see-through rim, or the panel's own border shows through it. */
body.wide .cam-bar::before { content: ''; position: absolute; top: -16px; right: -16px; bottom: -16px; left: -16px; background: #000; z-index: -1; }
body.wide #msg { right: 470px; }
#ad.bare #ad-win { border: 0; border-image: none; background: none; }
#ad.bare #ad-win h2 { bottom: -12px; right: 0; }
footer.short #foot-note { display: none; }
footer.short { padding-top: 8px; }
