/* image-hosting
   ------------------------------------------------------------------------
   One stylesheet for the whole site, served under a name that contains a hash
   of its contents so it is fetched once and then never again.

   It is written as tokens first and components second. Anything a page wants
   to look different about should be a variable here rather than a style
   attribute there.

   The palette is deliberately the least interesting one in the family. The
   sibling sites are a warm cookbook and a workshop-grey garage, because on
   those the page is the thing being looked at. Here the page is a frame: a
   coloured surround shifts how the colours inside a photograph read, and a
   library of pictures should not be tinted by the furniture around it. So the
   greys are neutral - no warmth, no blue - and the one accent appears on
   buttons and nowhere near a picture. */

/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: light dark;

  /* Surfaces, furthest to nearest: the page, the cards on it, the things that
     sit on a card, and a well for the things that sit under one. */
  --bg: #f7f7f8;
  --surface: #ffffff;
  --raised: #fbfbfc;
  --sunken: #eeeef1;

  --text: #17171a;
  --muted: #6b6b73;
  --faint: #97979f;
  --line: #e3e3e7;
  --line-strong: #cdcdd4;

  --accent: #3a5ccc;
  --accent-hover: #2f4bad;
  --accent-text: #ffffff;
  --accent-weak: #eef1fc;
  --accent-line: #d3dbf6;

  --error-bg: #fcecec;
  --error-text: #a32424;
  --ok-bg: #e8f4ec;
  --ok-text: #1c6b39;
  --warn-bg: #fdf3e2;
  --warn-text: #855313;

  /* The mat a picture is shown against. It is the same in both themes and
     darker than either page, because a photograph with light edges needs
     something to end against and a white one next to a white card does not. */
  --mat: #1c1c1f;

  --r-sm: 8px;
  --r-md: 11px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(20, 20, 25, 0.05);
  --shadow-md: 0 1px 3px rgba(20, 20, 25, 0.06), 0 6px 16px -6px rgba(20, 20, 25, 0.10);
  --shadow-lg: 0 2px 6px rgba(20, 20, 25, 0.07), 0 18px 40px -18px rgba(20, 20, 25, 0.20);

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* A monospace for the things that get copied rather than read: urls,
     markdown, an img tag. Seeing where a url ends matters more than it
     reading nicely. */
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --page: 1100px;
  --gutter: 24px;

  /* Tapping. 44px is the smallest thing a thumb hits reliably. */
  --tap: 44px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #111113;
    --surface: #1a1a1d;
    --raised: #212125;
    --sunken: #0d0d0f;

    --text: #f0f0f2;
    --muted: #9d9da6;
    --faint: #74747d;
    --line: #2c2c31;
    --line-strong: #3d3d44;

    --accent: #7c95ef;
    --accent-hover: #93a8f4;
    --accent-text: #0b1024;
    --accent-weak: #1a1f35;
    --accent-line: #2b3357;

    --error-bg: #391b1b;
    --error-text: #ffada6;
    --ok-bg: #14291d;
    --ok-text: #8fd6a6;
    --warn-bg: #32260f;
    --warn-text: #f0cd8a;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 1px 3px rgba(0, 0, 0, 0.45), 0 6px 16px -6px rgba(0, 0, 0, 0.6);
    --shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.5), 0 18px 40px -18px rgba(0, 0, 0, 0.75);
  }
}

/* ------------------------------------------------------------------ base */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  padding: var(--gutter) var(--gutter) 64px;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
}

/* Signed out pages are a single centred card; signed in pages are a page. */
body.centred {
  display: flex;
  align-items: center;
  justify-content: center;
  padding-bottom: var(--gutter);
}

body.centred main {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  padding: 32px 28px;
}

main {
  max-width: var(--page);
  margin: 0 auto;
}

main.wide { max-width: 1280px; }
main.narrow { max-width: 720px; }

h1 {
  font-size: 1.6rem;
  line-height: 1.25;
  margin: 0 0 12px;
  letter-spacing: -0.015em;
}

h2 {
  font-size: 1.15rem;
  margin: 0;
  letter-spacing: -0.01em;
}

p { margin: 0 0 16px; }
p.tight { margin-bottom: 6px; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }

.muted { color: var(--muted); }
.muted-small { color: var(--muted); font-size: 0.83rem; }
.faint { color: var(--faint); }

code, .mono { font-family: var(--font-mono); font-size: 0.9em; }

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 28px 0;
}

/* ------------------------------------------------------------ navigation */

.bar {
  max-width: 1280px;
  margin: 0 auto 24px;
}

.bar nav {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 6px 10px;
  box-shadow: var(--shadow-sm);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 650;
  color: var(--text);
  text-decoration: none;
  padding: 8px 12px;
  letter-spacing: -0.01em;
}

.bar .tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  text-decoration: none;
  padding: 8px 13px;
  border-radius: var(--r-pill);
  font-size: 0.92rem;
}

.bar .tab:hover { background: var(--sunken); color: var(--text); }
.bar .tab.on { background: var(--accent-weak); color: var(--accent); font-weight: 600; }

.spacer { flex: 1; }

.who {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
  padding: 8px 12px;
  border-radius: var(--r-pill);
  max-width: 190px;
}

.who:hover { background: var(--sunken); color: var(--text); }
.who.on { background: var(--accent-weak); color: var(--accent); }
.who .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The same links again along the bottom, for a phone. Only one of the two is
   ever on screen. */
.tabbar { display: none; }

@media (max-width: 720px) {
  .bar nav .tab { display: none; }

  /* The account link leaves the top bar rather than shrinking to its icon.
     Shrinking was the obvious move and it is wrong here: the icons are
     optional, so a site running without a Font Awesome kit would be left with
     a link that is an empty inline element - invisible, and still tappable.
     The bottom bar has Account on it, so nothing is lost by dropping this one.

     What stays is Sign out, because that is the one thing the tab bar has no
     room for and the one people go looking for on a borrowed machine. */
  .bar .who { display: none; }
  .brand { padding-left: 8px; }

  .tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    justify-content: space-around;
    background: var(--surface);
    border-top: 1px solid var(--line);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    z-index: 20;
  }

  .tabbar a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1;
    padding: 6px 2px;
    color: var(--muted);
    text-decoration: none;
    font-size: 0.68rem;
    min-height: var(--tap);
  }

  .tabbar a.on { color: var(--accent); font-weight: 600; }
  .tabbar .ico { font-size: 1.1rem; }

  body { padding-bottom: 92px; }
}

/* -------------------------------------------------------------- controls */

button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-weight: 600;
  font-size: 0.94rem;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s ease;
}

button:hover, .button:hover { background: var(--accent-hover); color: var(--accent-text); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

button.block, .button.block { width: 100%; }

button.quiet, .button.quiet {
  background: var(--surface);
  color: var(--text);
  border-color: var(--line-strong);
}

button.quiet:hover, .button.quiet:hover { background: var(--sunken); color: var(--text); }

button.danger {
  background: var(--surface);
  color: var(--error-text);
  border-color: var(--line-strong);
}

button.danger:hover { background: var(--error-bg); color: var(--error-text); }

button.link {
  background: none;
  border: none;
  color: var(--muted);
  font-weight: 500;
  padding: 8px 12px;
  min-height: auto;
  font-size: 0.9rem;
}

button.link:hover { background: var(--sunken); color: var(--text); }

button.small, .button.small {
  min-height: 34px;
  padding: 6px 13px;
  font-size: 0.85rem;
}

label {
  display: block;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--muted);
  margin: 0 0 6px;
}

input[type="text"], input[type="email"], input[type="search"], input[type="url"],
textarea, select {
  width: 100%;
  min-height: var(--tap);
  padding: 10px 14px;
  margin: 0 0 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
}

textarea { min-height: 90px; resize: vertical; line-height: 1.5; }

input:focus-visible, textarea:focus-visible, select:focus-visible,
button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

input.inline, select.inline { margin: 0; }

input[type="checkbox"] { width: auto; min-height: auto; accent-color: var(--accent); }

.fields {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: start;
}

.fields > * { flex: 1 1 220px; min-width: 0; }

.row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.row.end { justify-content: flex-end; }

/* --------------------------------------------------------------- banners */

.banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  background: var(--error-bg);
  color: var(--error-text);
  font-size: 0.92rem;
  margin: 0 0 18px;
}

.banner.ok { background: var(--ok-bg); color: var(--ok-text); }
.banner.warn { background: var(--warn-bg); color: var(--warn-text); }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  background: var(--sunken);
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 600;
  vertical-align: middle;
}

.pill.on { background: var(--accent-weak); color: var(--accent); }
.pill.warn { background: var(--warn-bg); color: var(--warn-text); }
.pill.ok { background: var(--ok-bg); color: var(--ok-text); }

.ico { width: 1em; text-align: center; }
.ico-accent { color: var(--accent); }

/* ---------------------------------------------------------- page heading */

.list-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin: 28px 0 14px;
}

.list-head .count { margin-left: auto; }

.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin: 0 0 20px;
}

.toolbar .grow { flex: 1 1 240px; min-width: 0; }

/* ---------------------------------------------------------------- upload */

.drop {
  border: 2px dashed var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: 34px 24px;
  text-align: center;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.drop.over {
  border-color: var(--accent);
  background: var(--accent-weak);
}

.drop h2 { margin-bottom: 6px; }
.drop p { margin: 6px 0 16px; color: var(--muted); font-size: 0.9rem; }

.drop input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* One row per file being uploaded, with its own progress and its own failure.
   A batch where the fourth file was a HEIC should upload the other three and
   say what happened to the fourth. */
.queue { margin: 18px 0 0; display: grid; gap: 8px; }

.queue .item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: 0.9rem;
  text-align: left;
}

.queue .item .name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.queue .item .state { color: var(--muted); font-size: 0.82rem; white-space: nowrap; }
.queue .item.failed { background: var(--error-bg); border-color: transparent; }
.queue .item.failed .state { color: var(--error-text); }
.queue .item.done .state { color: var(--ok-text); }

/* --------------------------------------------------------------- library */

.grid {
  display: grid;
  /* 148px rather than something more comfortable because of what the narrowest
     phone does with it: at 375px there is 327px of room, and a minimum above
     157px drops the grid to a single column - one photograph per screen, which
     is a viewer rather than a library. Two columns is the floor worth holding
     onto, and a wide screen fills out to whatever fits. */
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 14px;
}

@media (min-width: 900px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); }
}

.tile {
  position: relative;
  display: block;
  aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--mat);
  border: 1px solid var(--line);
  text-decoration: none;
}

.tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* A picture arriving is less jarring than a picture appearing. */
  transition: transform 0.18s ease;
}

.tile:hover img { transform: scale(1.03); }

/* The caption sits over the bottom of the picture rather than under it, so the
   tiles stay a grid of squares whatever the titles are doing. It is only drawn
   when there is something to say. */
.tile .caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 22px 10px 8px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0));
  color: #fff;
  font-size: 0.78rem;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tile .badge {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 600;
  backdrop-filter: blur(4px);
}

.empty {
  text-align: center;
  padding: 48px 24px;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.empty h2 { margin-bottom: 8px; color: var(--text); }

/* ----------------------------------------------------------- one picture */

.frame {
  background: var(--mat);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Tall enough to be a frame around a wide picture, and bounded so a portrait
     photograph does not need scrolling past to reach what is written about
     it. */
  min-height: 220px;
  max-height: 78vh;
}

.frame img {
  max-width: 100%;
  max-height: 78vh;
  display: block;
  object-fit: contain;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 20px 22px;
  margin: 18px 0 0;
}

.panel h2 { margin-bottom: 14px; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 18px;
  align-items: start;
}

@media (max-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr); }
}

/* Facts about a picture, as a list of label and value rather than a table:
   there is one of it, and a table of one row reads as a mistake. */
.facts { display: grid; gap: 10px; margin: 0; }

.facts > div {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  font-size: 0.88rem;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.facts > div:last-child { border-bottom: 0; padding-bottom: 0; }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; text-align: right; overflow-wrap: anywhere; }

/* --------------------------------------------------------- copyable urls */

.copy {
  display: flex;
  align-items: stretch;
  gap: 0;
  margin: 0 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--sunken);
}

.copy input {
  flex: 1;
  min-width: 0;
  margin: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  min-height: 40px;
  padding: 8px 12px;
}

.copy input:focus-visible { outline-offset: -2px; }

.copy button {
  border: 0;
  border-radius: 0;
  border-left: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  min-height: 40px;
  padding: 0 15px;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

.copy button:hover { background: var(--accent-weak); color: var(--accent); }
.copy button.done { background: var(--ok-bg); color: var(--ok-text); }

.copy + label { margin-top: 14px; }

/* ------------------------------------------------------------ share page */

/* What somebody who is not signed in sees: the picture, and a line under it.
   No navigation, nothing to join, nothing to scroll. */
.share {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 0;
}

.share .frame {
  width: 100%;
  max-height: 88vh;
  background: transparent;
}

.share .frame img { max-height: 88vh; }

.share .footer {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  color: var(--muted);
  font-size: 0.85rem;
}

body.share-page {
  padding: var(--gutter);
  background: var(--bg);
}

/* ---------------------------------------------------------------- tables */

.scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  font-size: 0.9rem;
}

th, td {
  text-align: left;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

th {
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: var(--raised);
  font-weight: 650;
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--raised); }

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

/* Everything above animates for feedback rather than for decoration, so there
   is nothing here that has to be replaced when it is turned off. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
